aboutsummaryrefslogtreecommitdiffstats
path: root/build/server.js
diff options
context:
space:
mode:
Diffstat (limited to 'build/server.js')
-rw-r--r--build/server.js1116
1 files changed, 868 insertions, 248 deletions
diff --git a/build/server.js b/build/server.js
index 5f68d3c..5b8b03f 100644
--- a/build/server.js
+++ b/build/server.js
@@ -1,4 +1,4 @@
-// Generated by Haxe 4.3.7
+// Generated by Haxe 4.3.3
(function ($global) { "use strict";
var $estr = function() { return js_Boot.__string_rec(this,''); },$hxEnums = $hxEnums || {},$_;
function $extend(from, fields) {
@@ -71,11 +71,18 @@ ClientTools.setLeader = function(clients,name) {
}
};
ClientTools.hasLeader = function(clients) {
+ return ClientTools.getLeader(clients) != null;
+};
+ClientTools.getLeader = function(clients) {
var _g = 0;
- while(_g < clients.length) if((clients[_g++].group & 4) != 0) {
- return true;
+ while(_g < clients.length) {
+ var client = clients[_g];
+ ++_g;
+ if((client.group & 4) != 0) {
+ return client;
+ }
}
- return false;
+ return null;
};
ClientTools.getByName = function(clients,name,def) {
var _g = 0;
@@ -759,7 +766,7 @@ JsonParser_$237c3c85cf00342dfb7f01e6a6157d10.prototype = $extend(json2object_rea
this.value = null;
}
,loadJsonString: function(s,pos,variable) {
- this.value = this.loadString(s,pos,variable,["RawType","YoutubeType","VkType","IframeType"],"RawType");
+ this.value = this.loadString(s,pos,variable,["RawType","YoutubeType","VkType","VimeoType","IframeType"],"RawType");
}
,__class__: JsonParser_$237c3c85cf00342dfb7f01e6a6157d10
});
@@ -1060,7 +1067,7 @@ JsonParser_$5f812affc76e9ba3f21130cdbd3b05d9.__name__ = true;
JsonParser_$5f812affc76e9ba3f21130cdbd3b05d9.__super__ = json2object_reader_BaseParser;
JsonParser_$5f812affc76e9ba3f21130cdbd3b05d9.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 }>, ?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));
+ 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, ?all : Null<Bool> }>, ?skipVideoStats : Null<{ voted : Int, total : Int, required : 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<{ ?url : Null<String>, 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) {
@@ -1068,7 +1075,7 @@ JsonParser_$5f812affc76e9ba3f21130cdbd3b05d9.prototype = $extend(json2object_rea
}
,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","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.objectSetupAssign(assigned,["addVideo","banClient","connected","dump","getTime","kickClient","login","logout","message","pause","play","playItem","progress","removeVideo","rewind","serverMessage","setLeader","setNextItem","setRate","setTime","skipVideo","skipVideoStats","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,true,false,true,true]);
this.value = this.getAuto();
var _g = 0;
while(_g < o.length) {
@@ -1112,7 +1119,7 @@ JsonParser_$5f812affc76e9ba3f21130cdbd3b05d9.prototype = $extend(json2object_rea
this.value.playItem = this.loadObjectField(($_=new JsonParser_$5696efcdbd81f0be9220dc4cfb255706(this.errors,this.putils,1),$bind($_,$_.loadJson)),field,"playItem",assigned,this.value.playItem,pos);
break;
case "progress":
- this.value.progress = this.loadObjectField(($_=new JsonParser_$e15c2211613da80aa2992b6249949a65(this.errors,this.putils,1),$bind($_,$_.loadJson)),field,"progress",assigned,this.value.progress,pos);
+ this.value.progress = this.loadObjectField(($_=new JsonParser_$df6a9f7e332eb07b32b03fe169ced290(this.errors,this.putils,1),$bind($_,$_.loadJson)),field,"progress",assigned,this.value.progress,pos);
break;
case "removeVideo":
this.value.removeVideo = this.loadObjectField(($_=new JsonParser_$bf1400338ef221d86126b3ec267cf395(this.errors,this.putils,1),$bind($_,$_.loadJson)),field,"removeVideo",assigned,this.value.removeVideo,pos);
@@ -1138,8 +1145,11 @@ JsonParser_$5f812affc76e9ba3f21130cdbd3b05d9.prototype = $extend(json2object_rea
case "skipVideo":
this.value.skipVideo = this.loadObjectField(($_=new JsonParser_$bf1400338ef221d86126b3ec267cf395(this.errors,this.putils,1),$bind($_,$_.loadJson)),field,"skipVideo",assigned,this.value.skipVideo,pos);
break;
+ case "skipVideoStats":
+ this.value.skipVideoStats = this.loadObjectField(($_=new JsonParser_$bd8ec2f9337eacbdc88803aa17adf898(this.errors,this.putils,1),$bind($_,$_.loadJson)),field,"skipVideoStats",assigned,this.value.skipVideoStats,pos);
+ break;
case "toggleItemType":
- this.value.toggleItemType = this.loadObjectField(($_=new JsonParser_$5696efcdbd81f0be9220dc4cfb255706(this.errors,this.putils,1),$bind($_,$_.loadJson)),field,"toggleItemType",assigned,this.value.toggleItemType,pos);
+ this.value.toggleItemType = this.loadObjectField(($_=new JsonParser_$d5567c7dc98bd09ace00c5da6aea116a(this.errors,this.putils,1),$bind($_,$_.loadJson)),field,"toggleItemType",assigned,this.value.toggleItemType,pos);
break;
case "togglePlaylistLock":
this.value.togglePlaylistLock = this.loadObjectField(($_=new JsonParser_$e5a960b500232cc84a0caf718de13706(this.errors,this.putils,1),$bind($_,$_.loadJson)),field,"togglePlaylistLock",assigned,this.value.togglePlaylistLock,pos);
@@ -1160,7 +1170,7 @@ JsonParser_$5f812affc76e9ba3f21130cdbd3b05d9.prototype = $extend(json2object_rea
this.objectErrors(assigned,pos);
}
,getAuto: function() {
- return { addVideo : new JsonParser_$17f62a9968afd16686d4888a98c34102([],this.putils,0).loadJson(new hxjsonast_Json(hxjsonast_JsonValue.JNull,new hxjsonast_Position("",0,1))), banClient : new JsonParser_$cceff829ad5e63207b6f78bebb03c69a([],this.putils,0).loadJson(new hxjsonast_Json(hxjsonast_JsonValue.JNull,new hxjsonast_Position("",0,1))), connected : new JsonParser_$d011018d886fa55f8828ebb1e93413c3([],this.putils,0).loadJson(new hxjsonast_Json(hxjsonast_JsonValue.JNull,new hxjsonast_Position("",0,1))), dump : new JsonParser_$dda5f87e2972892b16c7b833df96706a([],this.putils,0).loadJson(new hxjsonast_Json(hxjsonast_JsonValue.JNull,new hxjsonast_Position("",0,1))), getTime : new JsonParser_$feded5bdb427eb48f39e60029d5dca4a([],this.putils,0).loadJson(new hxjsonast_Json(hxjsonast_JsonValue.JNull,new hxjsonast_Position("",0,1))), kickClient : new JsonParser_$b2777fc36a3f1c43a2ae7d80ba0572ca([],this.putils,0).loadJson(new hxjsonast_Json(hxjsonast_JsonValue.JNull,new hxjsonast_Position("",0,1))), login : new JsonParser_$128275a4734b926daca1924fc6a200c7([],this.putils,0).loadJson(new hxjsonast_Json(hxjsonast_JsonValue.JNull,new hxjsonast_Position("",0,1))), logout : new JsonParser_$8d3a3702ec359ae3022bce905b75550b([],this.putils,0).loadJson(new hxjsonast_Json(hxjsonast_JsonValue.JNull,new hxjsonast_Position("",0,1))), message : new JsonParser_$33c34d246ae14cf949ef186cb0e1d8eb([],this.putils,0).loadJson(new hxjsonast_Json(hxjsonast_JsonValue.JNull,new hxjsonast_Position("",0,1))), pause : new JsonParser_$6340d11111c9ffddbd7ebb0d12d7c162([],this.putils,0).loadJson(new hxjsonast_Json(hxjsonast_JsonValue.JNull,new hxjsonast_Position("",0,1))), play : new JsonParser_$6340d11111c9ffddbd7ebb0d12d7c162([],this.putils,0).loadJson(new hxjsonast_Json(hxjsonast_JsonValue.JNull,new hxjsonast_Position("",0,1))), playItem : new JsonParser_$5696efcdbd81f0be9220dc4cfb255706([],this.putils,0).loadJson(new hxjsonast_Json(hxjsonast_JsonValue.JNull,new hxjsonast_Position("",0,1))), progress : new JsonParser_$e15c2211613da80aa2992b6249949a65([],this.putils,0).loadJson(new hxjsonast_Json(hxjsonast_JsonValue.JNull,new hxjsonast_Position("",0,1))), removeVideo : new JsonParser_$bf1400338ef221d86126b3ec267cf395([],this.putils,0).loadJson(new hxjsonast_Json(hxjsonast_JsonValue.JNull,new hxjsonast_Position("",0,1))), rewind : new JsonParser_$6340d11111c9ffddbd7ebb0d12d7c162([],this.putils,0).loadJson(new hxjsonast_Json(hxjsonast_JsonValue.JNull,new hxjsonast_Position("",0,1))), serverMessage : new JsonParser_$d1c1e71f4452df068de6cecc104f6dd6([],this.putils,0).loadJson(new hxjsonast_Json(hxjsonast_JsonValue.JNull,new hxjsonast_Position("",0,1))), setLeader : new JsonParser_$65985176838b1da92d970132a0cb6d58([],this.putils,0).loadJson(new hxjsonast_Json(hxjsonast_JsonValue.JNull,new hxjsonast_Position("",0,1))), setNextItem : new JsonParser_$5696efcdbd81f0be9220dc4cfb255706([],this.putils,0).loadJson(new hxjsonast_Json(hxjsonast_JsonValue.JNull,new hxjsonast_Position("",0,1))), setRate : new JsonParser_$359929cb56fda98b8740cbc66ef083c4([],this.putils,0).loadJson(new hxjsonast_Json(hxjsonast_JsonValue.JNull,new hxjsonast_Position("",0,1))), setTime : new JsonParser_$6340d11111c9ffddbd7ebb0d12d7c162([],this.putils,0).loadJson(new hxjsonast_Json(hxjsonast_JsonValue.JNull,new hxjsonast_Position("",0,1))), skipVideo : new JsonParser_$bf1400338ef221d86126b3ec267cf395([],this.putils,0).loadJson(new hxjsonast_Json(hxjsonast_JsonValue.JNull,new hxjsonast_Position("",0,1))), toggleItemType : new JsonParser_$5696efcdbd81f0be9220dc4cfb255706([],this.putils,0).loadJson(new hxjsonast_Json(hxjsonast_JsonValue.JNull,new hxjsonast_Position("",0,1))), togglePlaylistLock : new JsonParser_$e5a960b500232cc84a0caf718de13706([],this.putils,0).loadJson(new hxjsonast_Json(hxjsonast_JsonValue.JNull,new hxjsonast_Position("",0,1))), type : new JsonParser_$d8e5213783812cec0906ca233f0379dc([],this.putils,0).loadJson(new hxjsonast_Json(hxjsonast_JsonValue.JNull,new hxjsonast_Position("",0,1))), updateClients : new JsonParser_$126814d365d277a375ef70de1963f53d([],this.putils,0).loadJson(new hxjsonast_Json(hxjsonast_JsonValue.JNull,new hxjsonast_Position("",0,1))), updatePlaylist : new JsonParser_$a82c17fc41c21179c58e1d406d2b20cd([],this.putils,0).loadJson(new hxjsonast_Json(hxjsonast_JsonValue.JNull,new hxjsonast_Position("",0,1)))};
+ return { addVideo : new JsonParser_$17f62a9968afd16686d4888a98c34102([],this.putils,0).loadJson(new hxjsonast_Json(hxjsonast_JsonValue.JNull,new hxjsonast_Position("",0,1))), banClient : new JsonParser_$cceff829ad5e63207b6f78bebb03c69a([],this.putils,0).loadJson(new hxjsonast_Json(hxjsonast_JsonValue.JNull,new hxjsonast_Position("",0,1))), connected : new JsonParser_$d011018d886fa55f8828ebb1e93413c3([],this.putils,0).loadJson(new hxjsonast_Json(hxjsonast_JsonValue.JNull,new hxjsonast_Position("",0,1))), dump : new JsonParser_$dda5f87e2972892b16c7b833df96706a([],this.putils,0).loadJson(new hxjsonast_Json(hxjsonast_JsonValue.JNull,new hxjsonast_Position("",0,1))), getTime : new JsonParser_$feded5bdb427eb48f39e60029d5dca4a([],this.putils,0).loadJson(new hxjsonast_Json(hxjsonast_JsonValue.JNull,new hxjsonast_Position("",0,1))), kickClient : new JsonParser_$b2777fc36a3f1c43a2ae7d80ba0572ca([],this.putils,0).loadJson(new hxjsonast_Json(hxjsonast_JsonValue.JNull,new hxjsonast_Position("",0,1))), login : new JsonParser_$128275a4734b926daca1924fc6a200c7([],this.putils,0).loadJson(new hxjsonast_Json(hxjsonast_JsonValue.JNull,new hxjsonast_Position("",0,1))), logout : new JsonParser_$8d3a3702ec359ae3022bce905b75550b([],this.putils,0).loadJson(new hxjsonast_Json(hxjsonast_JsonValue.JNull,new hxjsonast_Position("",0,1))), message : new JsonParser_$33c34d246ae14cf949ef186cb0e1d8eb([],this.putils,0).loadJson(new hxjsonast_Json(hxjsonast_JsonValue.JNull,new hxjsonast_Position("",0,1))), pause : new JsonParser_$6340d11111c9ffddbd7ebb0d12d7c162([],this.putils,0).loadJson(new hxjsonast_Json(hxjsonast_JsonValue.JNull,new hxjsonast_Position("",0,1))), play : new JsonParser_$6340d11111c9ffddbd7ebb0d12d7c162([],this.putils,0).loadJson(new hxjsonast_Json(hxjsonast_JsonValue.JNull,new hxjsonast_Position("",0,1))), playItem : new JsonParser_$5696efcdbd81f0be9220dc4cfb255706([],this.putils,0).loadJson(new hxjsonast_Json(hxjsonast_JsonValue.JNull,new hxjsonast_Position("",0,1))), progress : new JsonParser_$df6a9f7e332eb07b32b03fe169ced290([],this.putils,0).loadJson(new hxjsonast_Json(hxjsonast_JsonValue.JNull,new hxjsonast_Position("",0,1))), removeVideo : new JsonParser_$bf1400338ef221d86126b3ec267cf395([],this.putils,0).loadJson(new hxjsonast_Json(hxjsonast_JsonValue.JNull,new hxjsonast_Position("",0,1))), rewind : new JsonParser_$6340d11111c9ffddbd7ebb0d12d7c162([],this.putils,0).loadJson(new hxjsonast_Json(hxjsonast_JsonValue.JNull,new hxjsonast_Position("",0,1))), serverMessage : new JsonParser_$d1c1e71f4452df068de6cecc104f6dd6([],this.putils,0).loadJson(new hxjsonast_Json(hxjsonast_JsonValue.JNull,new hxjsonast_Position("",0,1))), setLeader : new JsonParser_$65985176838b1da92d970132a0cb6d58([],this.putils,0).loadJson(new hxjsonast_Json(hxjsonast_JsonValue.JNull,new hxjsonast_Position("",0,1))), setNextItem : new JsonParser_$5696efcdbd81f0be9220dc4cfb255706([],this.putils,0).loadJson(new hxjsonast_Json(hxjsonast_JsonValue.JNull,new hxjsonast_Position("",0,1))), setRate : new JsonParser_$359929cb56fda98b8740cbc66ef083c4([],this.putils,0).loadJson(new hxjsonast_Json(hxjsonast_JsonValue.JNull,new hxjsonast_Position("",0,1))), setTime : new JsonParser_$6340d11111c9ffddbd7ebb0d12d7c162([],this.putils,0).loadJson(new hxjsonast_Json(hxjsonast_JsonValue.JNull,new hxjsonast_Position("",0,1))), skipVideo : new JsonParser_$bf1400338ef221d86126b3ec267cf395([],this.putils,0).loadJson(new hxjsonast_Json(hxjsonast_JsonValue.JNull,new hxjsonast_Position("",0,1))), skipVideoStats : new JsonParser_$bd8ec2f9337eacbdc88803aa17adf898([],this.putils,0).loadJson(new hxjsonast_Json(hxjsonast_JsonValue.JNull,new hxjsonast_Position("",0,1))), toggleItemType : new JsonParser_$d5567c7dc98bd09ace00c5da6aea116a([],this.putils,0).loadJson(new hxjsonast_Json(hxjsonast_JsonValue.JNull,new hxjsonast_Position("",0,1))), togglePlaylistLock : new JsonParser_$e5a960b500232cc84a0caf718de13706([],this.putils,0).loadJson(new hxjsonast_Json(hxjsonast_JsonValue.JNull,new hxjsonast_Position("",0,1))), type : new JsonParser_$d8e5213783812cec0906ca233f0379dc([],this.putils,0).loadJson(new hxjsonast_Json(hxjsonast_JsonValue.JNull,new hxjsonast_Position("",0,1))), updateClients : new JsonParser_$126814d365d277a375ef70de1963f53d([],this.putils,0).loadJson(new hxjsonast_Json(hxjsonast_JsonValue.JNull,new hxjsonast_Position("",0,1))), updatePlaylist : new JsonParser_$a82c17fc41c21179c58e1d406d2b20cd([],this.putils,0).loadJson(new hxjsonast_Json(hxjsonast_JsonValue.JNull,new hxjsonast_Position("",0,1)))};
}
,__class__: JsonParser_$5f812affc76e9ba3f21130cdbd3b05d9
});
@@ -1478,6 +1488,51 @@ JsonParser_$b3a4781c98609b64e4a870171c45561f.prototype = $extend(json2object_rea
}
,__class__: JsonParser_$b3a4781c98609b64e4a870171c45561f
});
+var JsonParser_$bd8ec2f9337eacbdc88803aa17adf898 = function(errors,putils,errorType) {
+ if(errorType == null) {
+ errorType = 0;
+ }
+ json2object_reader_BaseParser.call(this,errors,putils,errorType);
+};
+JsonParser_$bd8ec2f9337eacbdc88803aa17adf898.__name__ = true;
+JsonParser_$bd8ec2f9337eacbdc88803aa17adf898.__super__ = json2object_reader_BaseParser;
+JsonParser_$bd8ec2f9337eacbdc88803aa17adf898.prototype = $extend(json2object_reader_BaseParser.prototype,{
+ onIncorrectType: function(pos,variable) {
+ this.errors.push(json2object_Error.IncorrectType(variable,"{ voted : Int, total : Int, required : Int }",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,["required","total","voted"],[false,false,false]);
+ this.value = this.getAuto();
+ var _g = 0;
+ while(_g < o.length) {
+ var field = o[_g];
+ ++_g;
+ switch(field.name) {
+ case "required":
+ this.value.required = this.loadObjectField(($_=new JsonParser_$1686a6c336b71b36d77354cea19a8b52(this.errors,this.putils,1),$bind($_,$_.loadJson)),field,"required",assigned,this.value.required,pos);
+ break;
+ case "total":
+ this.value.total = this.loadObjectField(($_=new JsonParser_$1686a6c336b71b36d77354cea19a8b52(this.errors,this.putils,1),$bind($_,$_.loadJson)),field,"total",assigned,this.value.total,pos);
+ break;
+ case "voted":
+ this.value.voted = this.loadObjectField(($_=new JsonParser_$1686a6c336b71b36d77354cea19a8b52(this.errors,this.putils,1),$bind($_,$_.loadJson)),field,"voted",assigned,this.value.voted,pos);
+ break;
+ default:
+ this.errors.push(json2object_Error.UnknownVariable(field.name,this.putils.convertPosition(field.namePos)));
+ }
+ }
+ this.objectErrors(assigned,pos);
+ }
+ ,getAuto: function() {
+ return { required : new JsonParser_$1686a6c336b71b36d77354cea19a8b52([],this.putils,0).loadJson(new hxjsonast_Json(hxjsonast_JsonValue.JNull,new hxjsonast_Position("",0,1))), total : new JsonParser_$1686a6c336b71b36d77354cea19a8b52([],this.putils,0).loadJson(new hxjsonast_Json(hxjsonast_JsonValue.JNull,new hxjsonast_Position("",0,1))), voted : new JsonParser_$1686a6c336b71b36d77354cea19a8b52([],this.putils,0).loadJson(new hxjsonast_Json(hxjsonast_JsonValue.JNull,new hxjsonast_Position("",0,1)))};
+ }
+ ,__class__: JsonParser_$bd8ec2f9337eacbdc88803aa17adf898
+});
var JsonParser_$bf1400338ef221d86126b3ec267cf395 = function(errors,putils,errorType) {
if(errorType == null) {
errorType = 0;
@@ -1733,6 +1788,48 @@ JsonParser_$d1c1e71f4452df068de6cecc104f6dd6.prototype = $extend(json2object_rea
}
,__class__: JsonParser_$d1c1e71f4452df068de6cecc104f6dd6
});
+var JsonParser_$d5567c7dc98bd09ace00c5da6aea116a = function(errors,putils,errorType) {
+ if(errorType == null) {
+ errorType = 0;
+ }
+ json2object_reader_BaseParser.call(this,errors,putils,errorType);
+};
+JsonParser_$d5567c7dc98bd09ace00c5da6aea116a.__name__ = true;
+JsonParser_$d5567c7dc98bd09ace00c5da6aea116a.__super__ = json2object_reader_BaseParser;
+JsonParser_$d5567c7dc98bd09ace00c5da6aea116a.prototype = $extend(json2object_reader_BaseParser.prototype,{
+ onIncorrectType: function(pos,variable) {
+ this.errors.push(json2object_Error.IncorrectType(variable,"{ pos : Int, ?all : Null<Bool> }",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,["all","pos"],[true,false]);
+ this.value = this.getAuto();
+ var _g = 0;
+ while(_g < o.length) {
+ var field = o[_g];
+ ++_g;
+ switch(field.name) {
+ case "all":
+ this.value.all = this.loadObjectField(($_=new JsonParser_$f55acea3678203c700715b781ad1ef0c(this.errors,this.putils,1),$bind($_,$_.loadJson)),field,"all",assigned,this.value.all,pos);
+ break;
+ case "pos":
+ this.value.pos = this.loadObjectField(($_=new JsonParser_$1686a6c336b71b36d77354cea19a8b52(this.errors,this.putils,1),$bind($_,$_.loadJson)),field,"pos",assigned,this.value.pos,pos);
+ break;
+ default:
+ this.errors.push(json2object_Error.UnknownVariable(field.name,this.putils.convertPosition(field.namePos)));
+ }
+ }
+ this.objectErrors(assigned,pos);
+ }
+ ,getAuto: function() {
+ return { all : new JsonParser_$f55acea3678203c700715b781ad1ef0c([],this.putils,0).loadJson(new hxjsonast_Json(hxjsonast_JsonValue.JNull,new hxjsonast_Position("",0,1))), pos : new JsonParser_$1686a6c336b71b36d77354cea19a8b52([],this.putils,0).loadJson(new hxjsonast_Json(hxjsonast_JsonValue.JNull,new hxjsonast_Position("",0,1)))};
+ }
+ ,__class__: JsonParser_$d5567c7dc98bd09ace00c5da6aea116a
+});
var JsonParser_$d581436aae29874719279c60b2eb25d0 = function(errors,putils,errorType) {
if(errorType == null) {
errorType = 0;
@@ -1860,7 +1957,7 @@ JsonParser_$d89734267d6f665b411f49f013149267.__name__ = true;
JsonParser_$d89734267d6f665b411f49f013149267.__super__ = json2object_reader_BaseParser;
JsonParser_$d89734267d6f665b411f49f013149267.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));
+ this.errors.push(json2object_Error.IncorrectType(variable,"{ ?voiceOverTrack : Null<String>, url : String, title : String, ?subs : Null<String>, playerType : PlayerType, isTemp : Bool, ?isIncomplete : Null<Bool>, duration : Float, doCache : Bool, author : String }",pos));
json2object_reader_BaseParser.prototype.onIncorrectType.call(this,pos,variable);
}
,loadJsonNull: function(pos,variable) {
@@ -1868,7 +1965,7 @@ JsonParser_$d89734267d6f665b411f49f013149267.prototype = $extend(json2object_rea
}
,loadJsonObject: function(o,pos,variable) {
var assigned = new haxe_ds_StringMap();
- this.objectSetupAssign(assigned,["author","doCache","duration","isTemp","playerType","subs","title","url","voiceOverTrack"],[false,false,false,false,false,true,false,false,true]);
+ this.objectSetupAssign(assigned,["author","doCache","duration","isIncomplete","isTemp","playerType","subs","title","url","voiceOverTrack"],[false,false,false,true,false,false,true,false,false,true]);
this.value = this.getAuto();
var _g = 0;
while(_g < o.length) {
@@ -1884,6 +1981,9 @@ JsonParser_$d89734267d6f665b411f49f013149267.prototype = $extend(json2object_rea
case "duration":
this.value.duration = this.loadObjectField(($_=new JsonParser_$22ae0e2b89e5e3d477f988cc36d3272b(this.errors,this.putils,1),$bind($_,$_.loadJson)),field,"duration",assigned,this.value.duration,pos);
break;
+ case "isIncomplete":
+ this.value.isIncomplete = this.loadObjectField(($_=new JsonParser_$f55acea3678203c700715b781ad1ef0c(this.errors,this.putils,1),$bind($_,$_.loadJson)),field,"isIncomplete",assigned,this.value.isIncomplete,pos);
+ break;
case "isTemp":
this.value.isTemp = this.loadObjectField(($_=new JsonParser_$c26f15e86e3de4c398a8273272aba034(this.errors,this.putils,1),$bind($_,$_.loadJson)),field,"isTemp",assigned,this.value.isTemp,pos);
break;
@@ -1909,7 +2009,7 @@ JsonParser_$d89734267d6f665b411f49f013149267.prototype = $extend(json2object_rea
this.objectErrors(assigned,pos);
}
,getAuto: function() {
- return { author : new JsonParser_$27118326006d3829667a400ad23d5d98([],this.putils,0).loadJson(new hxjsonast_Json(hxjsonast_JsonValue.JNull,new hxjsonast_Position("",0,1))), doCache : new JsonParser_$c26f15e86e3de4c398a8273272aba034([],this.putils,0).loadJson(new hxjsonast_Json(hxjsonast_JsonValue.JNull,new hxjsonast_Position("",0,1))), duration : new JsonParser_$22ae0e2b89e5e3d477f988cc36d3272b([],this.putils,0).loadJson(new hxjsonast_Json(hxjsonast_JsonValue.JNull,new hxjsonast_Position("",0,1))), isTemp : new JsonParser_$c26f15e86e3de4c398a8273272aba034([],this.putils,0).loadJson(new hxjsonast_Json(hxjsonast_JsonValue.JNull,new hxjsonast_Position("",0,1))), playerType : new JsonParser_$237c3c85cf00342dfb7f01e6a6157d10([],this.putils,0).loadJson(new hxjsonast_Json(hxjsonast_JsonValue.JNull,new hxjsonast_Position("",0,1))), subs : new JsonParser_$ddce6d3de223cb2759be5c48797abca5([],this.putils,0).loadJson(new hxjsonast_Json(hxjsonast_JsonValue.JNull,new hxjsonast_Position("",0,1))), title : new JsonParser_$27118326006d3829667a400ad23d5d98([],this.putils,0).loadJson(new hxjsonast_Json(hxjsonast_JsonValue.JNull,new hxjsonast_Position("",0,1))), url : new JsonParser_$27118326006d3829667a400ad23d5d98([],this.putils,0).loadJson(new hxjsonast_Json(hxjsonast_JsonValue.JNull,new hxjsonast_Position("",0,1))), voiceOverTrack : new JsonParser_$ddce6d3de223cb2759be5c48797abca5([],this.putils,0).loadJson(new hxjsonast_Json(hxjsonast_JsonValue.JNull,new hxjsonast_Position("",0,1)))};
+ return { author : new JsonParser_$27118326006d3829667a400ad23d5d98([],this.putils,0).loadJson(new hxjsonast_Json(hxjsonast_JsonValue.JNull,new hxjsonast_Position("",0,1))), doCache : new JsonParser_$c26f15e86e3de4c398a8273272aba034([],this.putils,0).loadJson(new hxjsonast_Json(hxjsonast_JsonValue.JNull,new hxjsonast_Position("",0,1))), duration : new JsonParser_$22ae0e2b89e5e3d477f988cc36d3272b([],this.putils,0).loadJson(new hxjsonast_Json(hxjsonast_JsonValue.JNull,new hxjsonast_Position("",0,1))), isIncomplete : new JsonParser_$f55acea3678203c700715b781ad1ef0c([],this.putils,0).loadJson(new hxjsonast_Json(hxjsonast_JsonValue.JNull,new hxjsonast_Position("",0,1))), isTemp : new JsonParser_$c26f15e86e3de4c398a8273272aba034([],this.putils,0).loadJson(new hxjsonast_Json(hxjsonast_JsonValue.JNull,new hxjsonast_Position("",0,1))), playerType : new JsonParser_$237c3c85cf00342dfb7f01e6a6157d10([],this.putils,0).loadJson(new hxjsonast_Json(hxjsonast_JsonValue.JNull,new hxjsonast_Position("",0,1))), subs : new JsonParser_$ddce6d3de223cb2759be5c48797abca5([],this.putils,0).loadJson(new hxjsonast_Json(hxjsonast_JsonValue.JNull,new hxjsonast_Position("",0,1))), title : new JsonParser_$27118326006d3829667a400ad23d5d98([],this.putils,0).loadJson(new hxjsonast_Json(hxjsonast_JsonValue.JNull,new hxjsonast_Position("",0,1))), url : new JsonParser_$27118326006d3829667a400ad23d5d98([],this.putils,0).loadJson(new hxjsonast_Json(hxjsonast_JsonValue.JNull,new hxjsonast_Position("",0,1))), voiceOverTrack : new JsonParser_$ddce6d3de223cb2759be5c48797abca5([],this.putils,0).loadJson(new hxjsonast_Json(hxjsonast_JsonValue.JNull,new hxjsonast_Position("",0,1)))};
}
,__class__: JsonParser_$d89734267d6f665b411f49f013149267
});
@@ -1931,7 +2031,7 @@ JsonParser_$d8e5213783812cec0906ca233f0379dc.prototype = $extend(json2object_rea
this.value = null;
}
,loadJsonString: function(s,pos,variable) {
- 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","CrashTest"],"Connected");
+ this.value = this.loadString(s,pos,variable,["Connected","Disconnected","Login","PasswordRequest","LoginError","Logout","Message","ServerMessage","Progress","UpdateClients","BanClient","KickClient","AddVideo","RemoveVideo","SkipVideo","SkipVideoStats","VideoLoaded","Pause","Play","GetTime","SetTime","SetRate","Rewind","Flashback","SetLeader","PlayItem","SetNextItem","ToggleItemType","ClearChat","ClearPlaylist","ShufflePlaylist","UpdatePlaylist","TogglePlaylistLock","Dump","CrashTest"],"Connected");
}
,__class__: JsonParser_$d8e5213783812cec0906ca233f0379dc
});
@@ -1993,17 +2093,17 @@ JsonParser_$ddce6d3de223cb2759be5c48797abca5.prototype = $extend(json2object_rea
}
,__class__: JsonParser_$ddce6d3de223cb2759be5c48797abca5
});
-var JsonParser_$e15c2211613da80aa2992b6249949a65 = function(errors,putils,errorType) {
+var JsonParser_$df6a9f7e332eb07b32b03fe169ced290 = function(errors,putils,errorType) {
if(errorType == null) {
errorType = 0;
}
json2object_reader_BaseParser.call(this,errors,putils,errorType);
};
-JsonParser_$e15c2211613da80aa2992b6249949a65.__name__ = true;
-JsonParser_$e15c2211613da80aa2992b6249949a65.__super__ = json2object_reader_BaseParser;
-JsonParser_$e15c2211613da80aa2992b6249949a65.prototype = $extend(json2object_reader_BaseParser.prototype,{
+JsonParser_$df6a9f7e332eb07b32b03fe169ced290.__name__ = true;
+JsonParser_$df6a9f7e332eb07b32b03fe169ced290.__super__ = json2object_reader_BaseParser;
+JsonParser_$df6a9f7e332eb07b32b03fe169ced290.prototype = $extend(json2object_reader_BaseParser.prototype,{
onIncorrectType: function(pos,variable) {
- this.errors.push(json2object_Error.IncorrectType(variable,"{ type : ProgressType, ratio : Float, ?data : Null<String> }",pos));
+ this.errors.push(json2object_Error.IncorrectType(variable,"{ ?url : Null<String>, type : ProgressType, ratio : Float, ?data : Null<String> }",pos));
json2object_reader_BaseParser.prototype.onIncorrectType.call(this,pos,variable);
}
,loadJsonNull: function(pos,variable) {
@@ -2011,7 +2111,7 @@ JsonParser_$e15c2211613da80aa2992b6249949a65.prototype = $extend(json2object_rea
}
,loadJsonObject: function(o,pos,variable) {
var assigned = new haxe_ds_StringMap();
- this.objectSetupAssign(assigned,["data","ratio","type"],[true,false,false]);
+ this.objectSetupAssign(assigned,["data","ratio","type","url"],[true,false,false,true]);
this.value = this.getAuto();
var _g = 0;
while(_g < o.length) {
@@ -2027,6 +2127,9 @@ JsonParser_$e15c2211613da80aa2992b6249949a65.prototype = $extend(json2object_rea
case "type":
this.value.type = this.loadObjectField(($_=new JsonParser_$ec6c0149f584f56bd68388d292edf21c(this.errors,this.putils,1),$bind($_,$_.loadJson)),field,"type",assigned,this.value.type,pos);
break;
+ case "url":
+ this.value.url = this.loadObjectField(($_=new JsonParser_$ddce6d3de223cb2759be5c48797abca5(this.errors,this.putils,1),$bind($_,$_.loadJson)),field,"url",assigned,this.value.url,pos);
+ break;
default:
this.errors.push(json2object_Error.UnknownVariable(field.name,this.putils.convertPosition(field.namePos)));
}
@@ -2034,9 +2137,9 @@ JsonParser_$e15c2211613da80aa2992b6249949a65.prototype = $extend(json2object_rea
this.objectErrors(assigned,pos);
}
,getAuto: function() {
- return { data : new JsonParser_$ddce6d3de223cb2759be5c48797abca5([],this.putils,0).loadJson(new hxjsonast_Json(hxjsonast_JsonValue.JNull,new hxjsonast_Position("",0,1))), ratio : new JsonParser_$22ae0e2b89e5e3d477f988cc36d3272b([],this.putils,0).loadJson(new hxjsonast_Json(hxjsonast_JsonValue.JNull,new hxjsonast_Position("",0,1))), type : new JsonParser_$ec6c0149f584f56bd68388d292edf21c([],this.putils,0).loadJson(new hxjsonast_Json(hxjsonast_JsonValue.JNull,new hxjsonast_Position("",0,1)))};
+ return { data : new JsonParser_$ddce6d3de223cb2759be5c48797abca5([],this.putils,0).loadJson(new hxjsonast_Json(hxjsonast_JsonValue.JNull,new hxjsonast_Position("",0,1))), ratio : new JsonParser_$22ae0e2b89e5e3d477f988cc36d3272b([],this.putils,0).loadJson(new hxjsonast_Json(hxjsonast_JsonValue.JNull,new hxjsonast_Position("",0,1))), type : new JsonParser_$ec6c0149f584f56bd68388d292edf21c([],this.putils,0).loadJson(new hxjsonast_Json(hxjsonast_JsonValue.JNull,new hxjsonast_Position("",0,1))), url : new JsonParser_$ddce6d3de223cb2759be5c48797abca5([],this.putils,0).loadJson(new hxjsonast_Json(hxjsonast_JsonValue.JNull,new hxjsonast_Position("",0,1)))};
}
- ,__class__: JsonParser_$e15c2211613da80aa2992b6249949a65
+ ,__class__: JsonParser_$df6a9f7e332eb07b32b03fe169ced290
});
var JsonParser_$e5a960b500232cc84a0caf718de13706 = function(errors,putils,errorType) {
if(errorType == null) {
@@ -2093,7 +2196,7 @@ JsonParser_$ec6c0149f584f56bd68388d292edf21c.prototype = $extend(json2object_rea
this.value = null;
}
,loadJsonString: function(s,pos,variable) {
- this.value = this.loadString(s,pos,variable,["Caching","Downloading","Uploading","Canceled"],"Caching");
+ this.value = this.loadString(s,pos,variable,["Caching","Downloading","Uploading","Canceled","Completed"],"Caching");
}
,__class__: JsonParser_$ec6c0149f584f56bd68388d292edf21c
});
@@ -2519,8 +2622,14 @@ StringTools.hex = function(n,digits) {
};
var _$Types_VideoItemTools = function() { };
_$Types_VideoItemTools.__name__ = true;
+_$Types_VideoItemTools.isPlayable = function(item) {
+ if(item.isIncomplete == true && item.doCache) {
+ return false;
+ }
+ return true;
+};
_$Types_VideoItemTools.withUrl = function(item,url) {
- return { url : url, title : item.title, author : item.author, duration : item.duration, subs : item.subs, voiceOverTrack : item.voiceOverTrack, isTemp : item.isTemp, doCache : item.doCache, playerType : item.playerType};
+ return { url : url, title : item.title, author : item.author, duration : item.duration, subs : item.subs, voiceOverTrack : item.voiceOverTrack, isTemp : item.isTemp, doCache : item.doCache, isIncomplete : item.isIncomplete, playerType : item.playerType};
};
var VideoList = function() {
this.items = [];
@@ -2547,6 +2656,9 @@ VideoList.prototype = {
,exists: function(f) {
return Lambda.exists(this.items,f);
}
+ ,find: function(f) {
+ return Lambda.find(this.items,f);
+ }
,findIndex: function(f) {
return Lambda.findIndex(this.items,f);
}
@@ -2568,6 +2680,11 @@ VideoList.prototype = {
,toggleItemType: function(pos) {
this.items[pos].isTemp = !this.items[pos].isTemp;
}
+ ,setAllItemTypes: function(isTemp) {
+ var _g = 0;
+ var _g1 = this.items;
+ while(_g < _g1.length) _g1[_g++].isTemp = isTemp;
+ }
,removeItem: function(index) {
if(index < this.pos) {
this.pos--;
@@ -2860,7 +2977,14 @@ var haxe_ds_IntMap = function() {
haxe_ds_IntMap.__name__ = true;
haxe_ds_IntMap.__interfaces__ = [haxe_IMap];
haxe_ds_IntMap.prototype = {
- __class__: haxe_ds_IntMap
+ remove: function(key) {
+ if(!this.h.hasOwnProperty(key)) {
+ return false;
+ }
+ delete(this.h[key]);
+ return true;
+ }
+ ,__class__: haxe_ds_IntMap
};
var haxe_ds_StringMap = function() {
this.h = Object.create(null);
@@ -3139,6 +3263,7 @@ hxjsonast_JObjectField.prototype = {
__class__: hxjsonast_JObjectField
};
var hxjsonast_Parser = function(source,filename) {
+ this.allowDuplicateKeys = false;
this.source = source;
this.filename = filename;
this.pos = 0;
@@ -3296,7 +3421,7 @@ hxjsonast_Parser.prototype = {
var fieldStartPos = this.pos - 1;
field = this.parseString();
fieldPos = new hxjsonast_Position(this.filename,fieldStartPos,this.pos);
- if(Object.prototype.hasOwnProperty.call(names_h,field)) {
+ if(Object.prototype.hasOwnProperty.call(names_h,field) && !this.allowDuplicateKeys) {
throw haxe_Exception.thrown(new hxjsonast_Error("Duplicate field name \"" + field + "\"",fieldPos));
} else {
names_h[field] = true;
@@ -3942,8 +4067,9 @@ server_ConsoleInput.prototype = {
}
,__class__: server_ConsoleInput
};
-var server__$HttpServer_HttpServerConfig = function(dir,customDir,allowLocalRequests,cache) {
+var server__$HttpServer_HttpServerConfig = function(dir,customDir,allowLocalRequests,enableCORS,cache) {
this.cache = null;
+ this.enableCORS = false;
this.allowLocalRequests = false;
this.customDir = null;
this.dir = dir;
@@ -3953,6 +4079,9 @@ var server__$HttpServer_HttpServerConfig = function(dir,customDir,allowLocalRequ
if(allowLocalRequests != null) {
this.allowLocalRequests = allowLocalRequests;
}
+ if(enableCORS != null) {
+ this.enableCORS = enableCORS;
+ }
if(cache != null) {
this.cache = cache;
}
@@ -3969,6 +4098,7 @@ var server_HttpServer = function(main,config) {
this.uploadingFilesSizes = new haxe_ds_StringMap();
this.CHUNK_SIZE = 5242880;
this.cache = null;
+ this.enableCORS = false;
this.allowLocalRequests = false;
this.allowedLocalFiles = new haxe_ds_StringMap();
this.hasCustomRes = false;
@@ -3976,6 +4106,7 @@ var server_HttpServer = function(main,config) {
this.dir = config.dir;
this.customDir = config.customDir;
this.allowLocalRequests = config.allowLocalRequests;
+ this.enableCORS = config.enableCORS;
this.cache = config.cache;
if(this.customDir != null) {
this.hasCustomRes = sys_FileSystem.exists(this.customDir);
@@ -3993,6 +4124,17 @@ server_HttpServer.prototype = {
}
var filePath = this.getPath(this.dir,url);
var ext = haxe_io_Path.extension(filePath).toLowerCase();
+ if(this.enableCORS) {
+ res.setHeader("access-control-allow-origin","*");
+ res.setHeader("access-control-allow-headers","content-type, range, content-name, x-client-uuid");
+ res.setHeader("access-control-expose-headers","accept-ranges, content-encoding, content-length, content-range");
+ if(req.method == "OPTIONS") {
+ res.setHeader("access-control-allow-methods","GET, HEAD, POST, OPTIONS");
+ res.statusCode = 204;
+ res.end();
+ return;
+ }
+ }
res.setHeader("accept-ranges","bytes");
res.setHeader("content-type",this.getMimeType(ext));
if(req.method == "POST") {
@@ -4170,7 +4312,6 @@ server_HttpServer.prototype = {
if(Object.prototype.hasOwnProperty.call(_this.h,filePath)) {
delete(_this.h[filePath]);
}
- this.cache.remove(name);
req.destroy();
var tmp1 = ClientTools.getByName(this.main.clients,name);
if(tmp1 == null) {
@@ -4195,7 +4336,7 @@ server_HttpServer.prototype = {
}
});
stream.on("error",function(err) {
- haxe_Log.trace(err,{ fileName : "src/server/HttpServer.hx", lineNumber : 277, className : "server.HttpServer", methodName : "uploadFile"});
+ haxe_Log.trace(err,{ fileName : "src/server/HttpServer.hx", lineNumber : 291, className : "server.HttpServer", methodName : "uploadFile"});
tools_HttpServerTools.json(tools_HttpServerTools.status(res,500),{ info : "File write stream error."});
var _this = _gthis.uploadingFilesSizes;
if(Object.prototype.hasOwnProperty.call(_this.h,filePath)) {
@@ -4208,7 +4349,7 @@ server_HttpServer.prototype = {
_gthis.cache.remove(name);
});
req.on("error",function(err) {
- haxe_Log.trace("Request Error:",{ fileName : "src/server/HttpServer.hx", lineNumber : 284, className : "server.HttpServer", methodName : "uploadFile", customParams : [err]});
+ haxe_Log.trace("Request Error:",{ fileName : "src/server/HttpServer.hx", lineNumber : 298, className : "server.HttpServer", methodName : "uploadFile", customParams : [err]});
stream.destroy();
tools_HttpServerTools.json(tools_HttpServerTools.status(res,500),{ info : "File request error."});
var _this = _gthis.uploadingFilesSizes;
@@ -4386,12 +4527,18 @@ server_HttpServer.prototype = {
return true;
}
,parseRangeHeader: function(rangeHeader,videoSize) {
- var ranges = new EReg("[-=]","g").split(rangeHeader);
+ var ranges = new EReg("[=-]","g").split(rangeHeader);
var start = Std.parseInt(ranges[1]);
+ var end = Std.parseInt(ranges[2]);
+ if(start == null) {
+ var tmp = end;
+ var a = videoSize - (tmp != null ? tmp : 0);
+ start = a < 0 ? 0 : a;
+ end = videoSize - 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;
}
@@ -4614,8 +4761,8 @@ var server_Main = function(opts) {
this.loadedClientsCount = 0;
this.matchGuestName = new EReg("guest [0-9]+","");
this.matchHtmlChars = new EReg("[&^<>'\"]","");
+ this.cacheCancelers = new haxe_ds_StringMap();
this.skipVotes = new haxe_ds_IntMap();
- this.isServerPause = false;
this.flashbacks = [];
this.messages = [];
this.videoTimer = new server_VideoTimer();
@@ -4660,6 +4807,8 @@ var server_Main = function(opts) {
this.cache = new server_cache_Cache(this,this.cacheDir);
if(this.cache.isYtReady) {
this.playersCacheSupport.push("YoutubeType");
+ this.playersCacheSupport.push("VkType");
+ this.playersCacheSupport.push("VimeoType");
}
this.initIntergationHandlers();
this.loadState();
@@ -4687,7 +4836,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 : 159, 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 : 163, className : "server.Main", methodName : "new"});
attempts -= 1;
_gthis.port++;
preparePort();
@@ -4738,20 +4887,20 @@ server_Main.prototype = {
var protocol = ssl == null ? "http" : "https";
var port = this.getPort(protocol);
var colonPort = this.isDefaultPort() ? "" : ":" + port;
- haxe_Log.trace("Local: " + protocol + "://" + this.localIp + colonPort,{ fileName : "src/server/Main.hx", lineNumber : 189, className : "server.Main", methodName : "runServer"});
+ haxe_Log.trace("Local: " + protocol + "://" + this.localIp + colonPort,{ fileName : "src/server/Main.hx", lineNumber : 193, className : "server.Main", methodName : "runServer"});
if(this.config.localNetworkOnly) {
- haxe_Log.trace("Global network is disabled in config",{ fileName : "src/server/Main.hx", lineNumber : 191, className : "server.Main", methodName : "runServer"});
+ haxe_Log.trace("Global network is disabled in config",{ fileName : "src/server/Main.hx", lineNumber : 195, 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: " + protocol + "://" + _gthis.globalIp + colonPort,{ fileName : "src/server/Main.hx", lineNumber : 197, className : "server.Main", methodName : "runServer"});
+ haxe_Log.trace("Global: " + protocol + "://" + _gthis.globalIp + colonPort,{ fileName : "src/server/Main.hx", lineNumber : 201, className : "server.Main", methodName : "runServer"});
});
}
var dir = "" + this.rootDir + "/res";
- var httpServer = new server_HttpServer(this,new server__$HttpServer_HttpServerConfig(dir,"" + this.userDir + "/res",this.config.localAdmins,this.cache));
+ var httpServer = new server_HttpServer(this,new server__$HttpServer_HttpServerConfig(dir,"" + this.userDir + "/res",this.config.localAdmins,this.config.enableCORS,this.cache));
Lang.init("" + dir + "/langs");
var server;
if(ssl == null) {
@@ -4768,7 +4917,7 @@ server_Main.prototype = {
redirectHttpServer.listen(80);
} catch( _g ) {
var _g1 = haxe_Exception.caught(_g);
- haxe_Log.trace("Cannot run http server on port 80 for https redirects:",{ fileName : "src/server/Main.hx", lineNumber : 223, className : "server.Main", methodName : "runServer", customParams : [_g1]});
+ haxe_Log.trace("Cannot run http server on port 80 for https redirects:",{ fileName : "src/server/Main.hx", lineNumber : 228, className : "server.Main", methodName : "runServer", customParams : [_g1]});
}
}
server = js_node_Https.createServer({ key : ssl.key, cert : ssl.cert},$bind(httpServer,httpServer.serveFiles));
@@ -4805,10 +4954,10 @@ server_Main.prototype = {
return { key : key, cert : cert};
}
if(!sys_FileSystem.exists(config.sslKeyPemPath)) {
- haxe_Log.trace("sslKeyPemPath: absolute file path not found: " + config.sslKeyPemPath,{ fileName : "src/server/Main.hx", lineNumber : 261, className : "server.Main", methodName : "getSslConfig"});
+ haxe_Log.trace("sslKeyPemPath: absolute file path not found: " + config.sslKeyPemPath,{ fileName : "src/server/Main.hx", lineNumber : 266, className : "server.Main", methodName : "getSslConfig"});
}
if(!sys_FileSystem.exists(config.sslCertPemPath)) {
- haxe_Log.trace("sslCertPemPath: absolute file path not found: " + config.sslCertPemPath,{ fileName : "src/server/Main.hx", lineNumber : 263, className : "server.Main", methodName : "getSslConfig"});
+ haxe_Log.trace("sslCertPemPath: absolute file path not found: " + config.sslCertPemPath,{ fileName : "src/server/Main.hx", lineNumber : 268, className : "server.Main", methodName : "getSslConfig"});
}
return null;
}
@@ -4858,6 +5007,7 @@ server_Main.prototype = {
if(!sys_FileSystem.exists(customPath)) {
return config;
}
+ var defaultYtDlp = config.ytDlp;
var customConfig = JSON.parse(js_node_Fs.readFileSync(customPath,{ encoding : "utf8"}));
var _g = 0;
var _g1 = Reflect.fields(customConfig);
@@ -4865,10 +5015,12 @@ 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 : 308, className : "server.Main", methodName : "getUserConfig"});
+ haxe_Log.trace("Warning: config field \"" + field + "\" is unknown",{ fileName : "src/server/Main.hx", lineNumber : 314, className : "server.Main", methodName : "getUserConfig"});
}
config[field] = Reflect.field(customConfig,field);
}
+ config.ytDlp.channel = config.ytDlp.channel != null ? config.ytDlp.channel : defaultYtDlp.channel;
+ config.ytDlp.jsRuntime = config.ytDlp.jsRuntime != null ? config.ytDlp.jsRuntime : defaultYtDlp.jsRuntime;
var emoteCopies_h = Object.create(null);
var _g = 0;
var _g1 = config.emotes;
@@ -4876,14 +5028,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 : 314, className : "server.Main", methodName : "getUserConfig"});
+ haxe_Log.trace("Warning: emote name \"" + emote.name + "\" has copy",{ fileName : "src/server/Main.hx", lineNumber : 322, 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 : 318, className : "server.Main", methodName : "getUserConfig"});
+ haxe_Log.trace("Warning: emote url of name \"" + emote.name + "\" has copy",{ fileName : "src/server/Main.hx", lineNumber : 326, className : "server.Main", methodName : "getUserConfig"});
}
emoteCopies_h[emote.image] = true;
}
@@ -4920,7 +5072,7 @@ server_Main.prototype = {
js_node_Fs.writeFileSync("" + this.userDir + "/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 : 356, className : "server.Main", methodName : "saveState"});
+ haxe_Log.trace("Saving state...",{ fileName : "src/server/Main.hx", lineNumber : 364, className : "server.Main", methodName : "saveState"});
var json = JSON.stringify(this.getCurrentState(),null,"\t");
js_node_Fs.writeFileSync(this.statePath,json);
this.writeUsers(this.userList);
@@ -4935,7 +5087,7 @@ server_Main.prototype = {
if(!sys_FileSystem.exists(this.statePath)) {
return;
}
- haxe_Log.trace("Loading state...",{ fileName : "src/server/Main.hx", lineNumber : 380, className : "server.Main", methodName : "loadState"});
+ haxe_Log.trace("Loading state...",{ fileName : "src/server/Main.hx", lineNumber : 388, 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 : [];
@@ -4957,7 +5109,7 @@ server_Main.prototype = {
}
,logError: function(type,data) {
this.cache.removeOlderCache(1048576);
- haxe_Log.trace(type,{ fileName : "src/server/Main.hx", lineNumber : 404, className : "server.Main", methodName : "logError", customParams : [data]});
+ haxe_Log.trace(type,{ fileName : "src/server/Main.hx", lineNumber : 412, className : "server.Main", methodName : "logError", customParams : [data]});
var crashesFolder = "" + this.userDir + "/crashes";
server_Utils.ensureDir(crashesFolder);
var name = DateTools.format(new Date(),"%Y-%m-%d_%H_%M_%S") + "-" + type;
@@ -4979,7 +5131,7 @@ server_Main.prototype = {
if(_gthis.clients.length == 0) {
return;
}
- haxe_Log.trace("Ping " + url,{ fileName : "src/server/Main.hx", lineNumber : 417, className : "server.Main", methodName : "initIntergationHandlers"});
+ haxe_Log.trace("Ping " + url,{ fileName : "src/server/Main.hx", lineNumber : 425, className : "server.Main", methodName : "initIntergationHandlers"});
js_node_Http.get(url,null,function(r) {
});
};
@@ -5008,13 +5160,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 : 443, className : "server.Main", methodName : "addAdmin"});
+ haxe_Log.trace("Admin " + name + " added.",{ fileName : "src/server/Main.hx", lineNumber : 451, 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 : 450, className : "server.Main", methodName : "removeAdmin"});
+ haxe_Log.trace("Admin " + name + " removed.",{ fileName : "src/server/Main.hx", lineNumber : 458, className : "server.Main", methodName : "removeAdmin"});
}
,replayLog: function(events) {
var _gthis = this;
@@ -5081,7 +5233,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 : 513, className : "server.Main", methodName : "onConnect", customParams : ["" + name + " connected (" + ip + ")"]});
+ haxe_Log.trace(HxOverrides.dateStr(new Date()),{ fileName : "src/server/Main.hx", lineNumber : 521, className : "server.Main", methodName : "onConnect", customParams : ["" + name + " connected (" + ip + ")"]});
var remoteIp = req.socket.remoteAddress;
var isAdmin = this.config.localAdmins && this.isLoopbackIp(remoteIp);
var client = new Client(ws,req,id,name,0);
@@ -5096,7 +5248,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 : 531, className : "server.Main", methodName : "onConnect"});
+ haxe_Log.trace(errors,{ fileName : "src/server/Main.hx", lineNumber : 539, className : "server.Main", methodName : "onConnect"});
_gthis.serverMessage(client,errors);
return;
}
@@ -5171,47 +5323,55 @@ server_Main.prototype = {
data.addVideo.item = item;
_gthis.videoList.addItem(item,data.addVideo.atEnd);
_gthis.broadcast(data);
- if(_gthis.videoList.items.length == 1) {
+ if(_gthis.videoList.items.length == 1 && _$Types_VideoItemTools.isPlayable(item)) {
_gthis.restartWaitTimer();
}
- } else {
- var _g = item.playerType;
- switch(_g) {
- case "RawType":
- this.cache.cacheRawVideo(client,item.url,function(name) {
- item = _$Types_VideoItemTools.withUrl(item,_gthis.cache.getFileUrl(name));
- data.addVideo.item = item;
- _gthis.videoList.addItem(item,data.addVideo.atEnd);
- _gthis.broadcast(data);
- if(_gthis.videoList.items.length == 1) {
- _gthis.restartWaitTimer();
- }
- });
- break;
- case "YoutubeType":
- this.cache.cacheYoutubeVideo(client,item.url,function(name) {
- item = _$Types_VideoItemTools.withUrl(item,_gthis.cache.getFileUrl(name));
- if(item.duration > 1) {
- item.duration -= 1;
- }
- data.addVideo.item = item;
- _gthis.videoList.addItem(item,data.addVideo.atEnd);
- _gthis.broadcast(data);
- if(_gthis.videoList.items.length == 1) {
- _gthis.restartWaitTimer();
- }
- });
- break;
- default:
- var name = StringTools.replace("" + _g,"Type","");
- this.serverMessage(client,"No cache support for " + name + " player.");
- data.addVideo.item = item;
- _gthis.videoList.addItem(item,data.addVideo.atEnd);
- _gthis.broadcast(data);
- if(_gthis.videoList.items.length == 1) {
- _gthis.restartWaitTimer();
- }
+ return;
+ }
+ var isYoutube = item.playerType == "YoutubeType";
+ if(this.playersCacheSupport.indexOf(item.playerType) == -1) {
+ var name = StringTools.replace("" + item.playerType,"Type","");
+ this.serverMessage(client,"No cache support for " + name + " player.");
+ data.addVideo.item = item;
+ _gthis.videoList.addItem(item,data.addVideo.atEnd);
+ _gthis.broadcast(data);
+ if(_gthis.videoList.items.length == 1 && _$Types_VideoItemTools.isPlayable(item)) {
+ _gthis.restartWaitTimer();
}
+ return;
+ }
+ var callbacks = { onResolved : function(finalUrl) {
+ item = _$Types_VideoItemTools.withUrl(item,finalUrl);
+ item.isIncomplete = true;
+ if(isYoutube && item.duration > 1) {
+ item.duration -= 1;
+ }
+ data.addVideo.item = item;
+ _gthis.videoList.addItem(item,data.addVideo.atEnd);
+ _gthis.broadcast(data);
+ if(_gthis.videoList.items.length == 1 && _$Types_VideoItemTools.isPlayable(item)) {
+ _gthis.restartWaitTimer();
+ }
+ }, onProgress : function(ratio) {
+ _gthis.broadcastCacheProgress(item.url,ratio);
+ }, onComplete : function() {
+ _gthis.completeIncompleteItem(item.url);
+ }, onError : function() {
+ _gthis.removeIncompleteItem(item.url);
+ }, registerCancel : function(cancel) {
+ _gthis.cacheCancelers.h[item.url] = cancel;
+ }, onMetadata : function(title,duration) {
+ _gthis.updateIncompleteItemMeta(item.url,title,duration);
+ }};
+ switch(item.playerType) {
+ case "VimeoType":case "VkType":
+ this.cache.cacheYtdlpVideo(client,item.url,callbacks);
+ break;
+ case "YoutubeType":
+ this.cache.cacheYoutubeVideo(client,item.url,callbacks);
+ break;
+ default:
+ this.cache.cacheRawVideo(client,item.url,callbacks);
}
break;
case "BanClient":
@@ -5257,10 +5417,10 @@ server_Main.prototype = {
if(this.isPlaylistLockedFor(client)) {
return;
}
- this.resetSkipVote();
if(!this.checkPermission(client,"removeVideo")) {
return;
}
+ this.resetSkipVote();
if(this.videoList.items.length != 0) {
if(this.videoTimer.getTime() > 30) {
var _this = this.videoList;
@@ -5282,7 +5442,7 @@ server_Main.prototype = {
tmp.stop();
}
if(this.clients.length == 1 && this.videoList.items.length > 0) {
- if(!this.isServerPause) {
+ if(!this.videoTimer.isServerPause) {
if(this.videoTimer.isPaused()) {
this.videoTimer.play();
}
@@ -5291,28 +5451,31 @@ server_Main.prototype = {
this.checkBan(client);
this.send(client,{ type : "Connected", connected : { uuid : client.uuid, config : { channelName : this.config.channelName, emotes : this.config.emotes, filters : this.config.filters, isVerbose : this.config.isVerbose, maxLoginLength : this.config.maxLoginLength, maxMessageLength : this.config.maxMessageLength, permissions : this.config.permissions, port : this.config.port, requestLeaderOnPause : this.config.requestLeaderOnPause, salt : this.config.salt, serverVersion : this.config.serverVersion, templateUrl : this.config.templateUrl, totalVideoLimit : this.config.totalVideoLimit, unpauseWithoutLeader : this.config.unpauseWithoutLeader, userVideoLimit : this.config.userVideoLimit, youtubeApiKey : this.config.youtubeApiKey, youtubePlaylistLimit : this.config.youtubePlaylistLimit}, history : this.messages, isUnknownClient : true, clientName : client.name, clients : this.clientList(), videoList : this.videoList.items, isPlaylistOpen : this.videoList.isOpen, itemPos : this.videoList.pos, globalIp : this.globalIp, playersCacheSupport : this.playersCacheSupport}});
this.sendClientListExcept(client);
+ this.broadcastSkipVoteStats();
break;
case "CrashTest":
if((client.group & 8) == 0) {
return;
}
- haxe_Log.trace("Crashing...",{ fileName : "src/server/Main.hx", lineNumber : 1073, className : "server.Main", methodName : "onMessage"});
+ haxe_Log.trace("Crashing...",{ fileName : "src/server/Main.hx", lineNumber : 1132, className : "server.Main", methodName : "onMessage"});
null[1]++;
break;
case "Disconnected":
if(!internal) {
return;
}
- haxe_Log.trace(HxOverrides.dateStr(new Date()),{ fileName : "src/server/Main.hx", lineNumber : 596, className : "server.Main", methodName : "onMessage", customParams : ["Client " + client.name + " disconnected"]});
+ haxe_Log.trace(HxOverrides.dateStr(new Date()),{ fileName : "src/server/Main.hx", lineNumber : 605, className : "server.Main", methodName : "onMessage", customParams : ["Client " + client.name + " disconnected"]});
server_Utils.sortedPush(this.freeIds,client.id);
HxOverrides.remove(this.clients,client);
this.sendClientList();
if((client.group & 4) != 0) {
if(this.videoList.items.length > 0) {
this.videoTimer.pause();
- this.isServerPause = true;
+ this.videoTimer.isServerPause = true;
}
}
+ this.skipVotes.remove(client.id);
+ this.updateSkipVote();
if(this.clients.length == 0) {
var tmp = this.emptyRoomCallbackTimer;
if(tmp != null) {
@@ -5373,6 +5536,10 @@ server_Main.prototype = {
return;
}
var _this = this.videoList;
+ if(_this.items[_this.pos].isIncomplete) {
+ return;
+ }
+ var _this = this.videoList;
var maxTime = _this.items[_this.pos].duration - 0.01;
if(this.videoTimer.getTime() > maxTime) {
this.videoTimer.pause();
@@ -5388,7 +5555,7 @@ server_Main.prototype = {
if(this.videoTimer.isPaused()) {
obj.getTime.paused = true;
}
- if(this.isServerPause) {
+ if(this.videoTimer.isServerPause) {
obj.getTime.pausedByServer = true;
}
if(this.videoTimer.getRate() != 1) {
@@ -5444,12 +5611,13 @@ server_Main.prototype = {
this.send(client,{ type : "LoginError"});
return;
}
- haxe_Log.trace(HxOverrides.dateStr(new Date()),{ fileName : "src/server/Main.hx", lineNumber : 687, 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 : 698, className : "server.Main", methodName : "onMessage", customParams : ["Client " + client.name + " logged as " + name]});
client.name = name;
client.setGroupFlag(ClientGroup.User,true);
this.checkBan(client);
this.send(client,{ type : data.type, login : { isUnknownClient : true, clientName : client.name, clients : this.clientList()}});
this.sendClientListExcept(client);
+ this.broadcastSkipVoteStats();
break;
case "LoginError":
break;
@@ -5457,9 +5625,10 @@ 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 : 708, 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 : 720, 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);
+ this.broadcastSkipVoteStats();
break;
case "Message":
if(!this.checkPermission(client,"writeChat")) {
@@ -5511,7 +5680,6 @@ server_Main.prototype = {
this.saveFlashbackTime(_this.items[_this.pos]);
}
this.videoTimer.setTime(data.play.time);
- this.isServerPause = false;
this.videoTimer.play();
this.broadcast({ type : data.type, play : data.play});
break;
@@ -5519,11 +5687,11 @@ server_Main.prototype = {
if(!this.checkPermission(client,"changeOrder")) {
return;
}
- this.resetSkipVote();
var pos = data.playItem.pos;
if(!this.videoList.hasItem(pos)) {
return;
}
+ this.resetSkipVote();
if(this.videoTimer.getTime() > 30) {
var _this = this.videoList;
this.saveFlashbackTime(_this.items[_this.pos]);
@@ -5534,37 +5702,80 @@ server_Main.prototype = {
this.broadcast(data);
break;
case "Progress":
+ var p = data.progress;
+ var url;
+ var tmp = p.url;
+ if(tmp != null) {
+ url = tmp;
+ } else {
+ return;
+ }
+ var index = this.videoList.findIndex(function(i) {
+ return i.url == url;
+ });
+ if(index == -1) {
+ return;
+ }
+ var item1 = this.videoList.items[index];
+ if(item1.isIncomplete != true) {
+ return;
+ }
+ if(item1.doCache) {
+ return;
+ }
+ if(item1.author != client.name) {
+ return;
+ }
+ switch(p.type) {
+ case "Canceled":
+ this.removeIncompleteItem(url);
+ break;
+ case "Completed":
+ this.completeIncompleteItem(url);
+ break;
+ default:
+ this.broadcast(data);
+ }
break;
case "RemoveVideo":
if(this.videoList.items.length == 0) {
return;
}
- if(this.activeSkipVoteUrl == data.removeVideo.url) {
- this.resetSkipVote();
- }
if(this.isPlaylistLockedFor(client)) {
return;
}
if(!this.checkPermission(client,"removeVideo")) {
return;
}
- var url = data.removeVideo.url;
+ var url1 = data.removeVideo.url;
var index = this.videoList.findIndex(function(item) {
- return item.url == url;
+ return item.url == url1;
});
if(index == -1) {
return;
}
var _this = this.videoList;
- var isCurrent = _this.items[_this.pos].url == url;
+ var isCurrent = _this.items[_this.pos].url == url1;
+ if(isCurrent) {
+ this.resetSkipVote();
+ }
if(isCurrent && this.videoTimer.getTime() > 30) {
var _this = this.videoList;
this.saveFlashbackTime(_this.items[_this.pos]);
}
this.videoList.removeItem(index);
+ this.cancelCache(url1);
this.broadcast(data);
if(isCurrent && this.videoList.items.length > 0) {
- this.restartWaitTimer();
+ var _this = this.videoList;
+ if(!_$Types_VideoItemTools.isPlayable(_this.items[_this.pos])) {
+ this.pauseForIncompleteItem();
+ } else {
+ this.restartWaitTimer();
+ }
+ }
+ if(this.videoList.items.length == 0) {
+ this.videoTimer.stop();
}
break;
case "Rewind":
@@ -5610,7 +5821,7 @@ server_Main.prototype = {
this.serverMessage(client,"Client \"" + clientName + "\" not found.");
return;
}
- this.isServerPause = false;
+ this.videoTimer.isServerPause = false;
ClientTools.setLeader(this.clients,clientName);
this.broadcast({ type : "SetLeader", setLeader : { clientName : clientName}});
if(this.videoList.items.length == 0) {
@@ -5684,6 +5895,8 @@ server_Main.prototype = {
}
this.handleSkipVote(client,data);
break;
+ case "SkipVideoStats":
+ break;
case "ToggleItemType":
if(this.isPlaylistLockedFor(client)) {
return;
@@ -5695,6 +5908,11 @@ server_Main.prototype = {
if(!this.videoList.hasItem(pos)) {
return;
}
+ if(data.toggleItemType.all == true) {
+ this.videoList.setAllItemTypes(!this.videoList.items[pos].isTemp);
+ this.broadcast({ type : "UpdatePlaylist", updatePlaylist : { videoList : this.videoList.items}});
+ return;
+ }
this.videoList.toggleItemType(pos);
this.broadcast(data);
break;
@@ -5712,7 +5930,7 @@ server_Main.prototype = {
this.broadcast({ type : "UpdatePlaylist", updatePlaylist : { videoList : this.videoList.items}});
break;
case "VideoLoaded":
- if(this.isServerPause) {
+ if(this.videoTimer.isServerPause) {
return;
}
this.prepareVideoPlayback();
@@ -5738,13 +5956,6 @@ server_Main.prototype = {
,send: function(client,data) {
client.ws.send(server_Main.jsonStringify(data),null);
}
- ,sendByName: function(clientName,data) {
- var tmp = ClientTools.getByName(this.clients,clientName);
- if(tmp == null) {
- return;
- }
- tmp.ws.send(server_Main.jsonStringify(data),null);
- }
,broadcast: function(data) {
var json = server_Main.jsonStringify(data);
var _g = 0;
@@ -5823,23 +6034,44 @@ server_Main.prototype = {
return;
}
this.skipVotes.h[client.id] = true;
- var votes = this.getSkipVoteCount();
- var required = this.getSkipVoteRequiredCount();
- this.broadcast({ type : "ServerMessage", serverMessage : { textId : "" + client.name + " voted to skip (" + votes + "/" + required + ")."}});
- if(votes >= required) {
+ this.updateSkipVote();
+ }
+ ,updateSkipVote: function() {
+ if(this.activeSkipVoteUrl == null) {
+ return;
+ }
+ var tmp;
+ if(this.videoList.items.length != 0) {
+ var _this = this.videoList;
+ tmp = _this.items[_this.pos].url != this.activeSkipVoteUrl;
+ } else {
+ tmp = true;
+ }
+ if(tmp) {
this.resetSkipVote();
- this.skipVideo(data);
+ return;
+ }
+ if(this.getSkipVoteCount() >= this.getSkipVoteRequiredCount()) {
+ this.skipVideo({ type : "SkipVideo", skipVideo : { url : this.activeSkipVoteUrl}});
+ return;
}
+ this.broadcastSkipVoteStats();
+ }
+ ,broadcastSkipVoteStats: function() {
+ if(this.activeSkipVoteUrl == null) {
+ return;
+ }
+ this.broadcast({ type : "SkipVideoStats", skipVideoStats : { voted : this.getSkipVoteCount(), total : this.getSkipVoteEligibleClients().length, required : this.getSkipVoteRequiredCount()}});
}
,skipVideo: function(data) {
if(this.videoList.items.length == 0) {
return;
}
- this.resetSkipVote();
var _this = this.videoList;
if(_this.items[_this.pos].url != data.skipVideo.url) {
return;
}
+ this.resetSkipVote();
var _this = this.videoList;
var dur = _this.items[_this.pos].duration;
if(this.videoTimer.getTime() > 30 && this.videoTimer.getTime() < dur - 30) {
@@ -5848,10 +6080,100 @@ server_Main.prototype = {
}
this.videoList.skipItem();
if(this.videoList.items.length > 0) {
- this.restartWaitTimer();
+ var _this = this.videoList;
+ if(!_$Types_VideoItemTools.isPlayable(_this.items[_this.pos])) {
+ this.pauseForIncompleteItem();
+ } else {
+ this.restartWaitTimer();
+ }
+ } else {
+ this.videoTimer.stop();
}
this.broadcast(data);
}
+ ,pauseForIncompleteItem: function() {
+ this.videoTimer.stop();
+ var tmp = this.waitVideoStart;
+ if(tmp != null) {
+ tmp.stop();
+ }
+ }
+ ,cancelCache: function(url) {
+ var tmp = this.cacheCancelers.h[url];
+ if(tmp == null) {
+ return;
+ }
+ var _this = this.cacheCancelers;
+ if(Object.prototype.hasOwnProperty.call(_this.h,url)) {
+ delete(_this.h[url]);
+ }
+ tmp();
+ }
+ ,broadcastCacheProgress: function(url,ratio) {
+ this.broadcast({ type : "Progress", progress : { type : "Downloading", ratio : ratio, url : url}});
+ }
+ ,updateIncompleteItemMeta: function(url,title,duration) {
+ var tmp = this.videoList.find(function(item) {
+ return item.url == url;
+ });
+ if(tmp == null) {
+ return;
+ }
+ if(tmp.isIncomplete != true) {
+ return;
+ }
+ var changed = false;
+ if(tmp.duration <= 0 && duration > 0) {
+ tmp.duration = duration;
+ changed = true;
+ }
+ if(title != null && title.length > 0 && tmp.title.length == 0) {
+ tmp.title = title;
+ changed = true;
+ }
+ if(!changed) {
+ return;
+ }
+ this.broadcast({ type : "UpdatePlaylist", updatePlaylist : { videoList : this.videoList.items}});
+ }
+ ,completeIncompleteItem: function(url) {
+ var _this = this.cacheCancelers;
+ if(Object.prototype.hasOwnProperty.call(_this.h,url)) {
+ delete(_this.h[url]);
+ }
+ var index = this.videoList.findIndex(function(i) {
+ return i.url == url;
+ });
+ if(index == -1) {
+ return;
+ }
+ var item = this.videoList.items[index];
+ if(item.isIncomplete != true) {
+ return;
+ }
+ item.isIncomplete = false;
+ this.broadcast({ type : "Progress", progress : { type : "Completed", ratio : 1, url : url}});
+ if(this.videoList.pos == index && item.doCache) {
+ this.restartWaitTimer();
+ }
+ }
+ ,removeIncompleteItem: function(url) {
+ var _this = this.cacheCancelers;
+ if(Object.prototype.hasOwnProperty.call(_this.h,url)) {
+ delete(_this.h[url]);
+ }
+ var index = this.videoList.findIndex(function(i) {
+ return i.url == url;
+ });
+ if(index == -1) {
+ return;
+ }
+ if(this.videoList.items[index].isIncomplete != true) {
+ return;
+ }
+ this.videoList.removeItem(index);
+ this.broadcast({ type : "RemoveVideo", removeVideo : { url : url}});
+ }
,checkPermission: function(client,perm) {
if((client.group & 1) != 0) {
this.checkBan(client);
@@ -5880,7 +6202,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 : 1255, className : "server.Main", methodName : "checkBan"});
+ haxe_Log.trace("" + client.name + " ban removed",{ fileName : "src/server/Main.hx", lineNumber : 1415, className : "server.Main", methodName : "checkBan"});
this.sendClientList();
}
break;
@@ -5933,7 +6255,6 @@ server_Main.prototype = {
}
this.loadedClientsCount = 0;
this.broadcast({ type : "VideoLoaded"});
- this.isServerPause = false;
this.videoTimer.start();
}
,saveFlashbackTime: function(item) {
@@ -6064,7 +6385,7 @@ server_Utils.getGlobalIp = function(callback) {
data_b += Std.string(chunk);
});
r.on("end",function() {
- callback(data_b);
+ callback(StringTools.trim(data_b));
});
}).on("error",onError).on("timeout",onError);
};
@@ -6106,12 +6427,14 @@ var server_VideoTimer = function() {
this.rateStartTime = 0.0;
this.pauseStartTime = 0.0;
this.startTime = 0.0;
+ this.isServerPause = false;
this.isStarted = false;
};
server_VideoTimer.__name__ = true;
server_VideoTimer.prototype = {
start: function() {
this.isStarted = true;
+ this.isServerPause = false;
var hrtime = process.hrtime();
this.startTime = hrtime[0] + hrtime[1] / 1e9;
this.pauseStartTime = 0;
@@ -6120,6 +6443,7 @@ server_VideoTimer.prototype = {
}
,stop: function() {
this.isStarted = false;
+ this.isServerPause = false;
this.startTime = 0;
this.pauseStartTime = 0;
}
@@ -6139,6 +6463,7 @@ server_VideoTimer.prototype = {
if(!this.isStarted) {
this.start();
}
+ this.isServerPause = false;
this.startTime += this.pauseTime();
this.pauseStartTime = 0;
var hrtime = process.hrtime();
@@ -6203,12 +6528,13 @@ var server_cache_Cache = function(main,cacheDir) {
this.main = main;
this.cacheDir = cacheDir;
server_Utils.ensureDir(cacheDir);
- this.youtubeCache = new server_cache_YoutubeCache(main,this);
+ this.ytdlpCache = new server_cache_YtdlpCache(main,this);
+ this.youtubeCache = new server_cache_YoutubeCache(main,this,this.ytdlpCache);
this.rawCache = new server_cache_RawCache(main,this);
- this.isYtReady = this.youtubeCache.checkYtDeps();
+ this.isYtReady = this.ytdlpCache.checkYtDeps();
if(this.isYtReady) {
- this.youtubeCache.cleanYtInputFiles();
- this.youtubeCache.checkUpdate();
+ this.ytdlpCache.cleanInputFiles();
+ this.ytdlpCache.checkUpdate();
}
};
server_cache_Cache.__name__ = true;
@@ -6237,16 +6563,16 @@ server_cache_Cache.prototype = {
if(this.cachedFiles.indexOf(name) != -1) {
continue;
}
- haxe_Log.trace("Remove untracked cache " + name,{ fileName : "src/server/cache/Cache.hx", lineNumber : 54, className : "server.cache.Cache", methodName : "removeUntrackedFiles"});
+ haxe_Log.trace("Remove untracked cache " + name,{ fileName : "src/server/cache/Cache.hx", lineNumber : 56, className : "server.cache.Cache", methodName : "removeUntrackedFiles"});
this.remove(name);
}
}
,log: function(client,msg) {
- haxe_Log.trace(msg,{ fileName : "src/server/cache/Cache.hx", lineNumber : 60, className : "server.cache.Cache", methodName : "log"});
+ haxe_Log.trace(msg,{ fileName : "src/server/cache/Cache.hx", lineNumber : 62, className : "server.cache.Cache", methodName : "log"});
this.main.serverMessage(client,msg);
}
,logByName: function(clientName,msg) {
- haxe_Log.trace(msg,{ fileName : "src/server/cache/Cache.hx", lineNumber : 65, className : "server.cache.Cache", methodName : "logByName"});
+ haxe_Log.trace(msg,{ fileName : "src/server/cache/Cache.hx", lineNumber : 67, className : "server.cache.Cache", methodName : "logByName"});
var tmp = ClientTools.getByName(this.main.clients,clientName);
if(tmp == null) {
return;
@@ -6274,11 +6600,29 @@ server_cache_Cache.prototype = {
}
}
}
- ,cacheYoutubeVideo: function(client,url,callback) {
- this.youtubeCache.cacheYoutubeVideo(client,url,callback);
+ ,cacheYoutubeVideo: function(client,url,callbacks) {
+ this.youtubeCache.cacheYoutubeVideo(client,url,callbacks);
+ }
+ ,cacheYtdlpVideo: function(client,url,callbacks) {
+ if(!this.isYtReady) {
+ this.rawCache.cacheRawVideo(client,url,callbacks);
+ return;
+ }
+ this.ytdlpCache.cacheVideo(client,url,callbacks);
}
- ,cacheRawVideo: function(client,url,callback) {
- this.rawCache.cacheRawVideo(client,url,callback);
+ ,cacheRawVideo: function(client,url,callbacks) {
+ var _gthis = this;
+ if(!this.isYtReady) {
+ this.rawCache.cacheRawVideo(client,url,callbacks);
+ return;
+ }
+ this.ytdlpCache.checkUrlSupported(url,function(supported) {
+ if(supported) {
+ _gthis.ytdlpCache.cacheVideo(client,url,callbacks);
+ } else {
+ _gthis.rawCache.cacheRawVideo(client,url,callbacks);
+ }
+ });
}
,setStorageLimit: function(bytes) {
var _gthis = this;
@@ -6301,13 +6645,13 @@ server_cache_Cache.prototype = {
var _gthis = this;
var tmp = js_node_Fs.statfs;
if(tmp == null) {
- haxe_Log.trace("Warning: no fs.statfs support in current nodejs version (needs v18+)",{ fileName : "src/server/cache/Cache.hx", lineNumber : 104, className : "server.cache.Cache", methodName : "getFreeDiskSpace"});
+ haxe_Log.trace("Warning: no fs.statfs support in current nodejs version (needs v18+)",{ fileName : "src/server/cache/Cache.hx", lineNumber : 125, className : "server.cache.Cache", methodName : "getFreeDiskSpace"});
callback(this.storageLimit);
return;
}
- tmp("/",function(err,stats) {
+ tmp(this.cacheDir,function(err,stats) {
if(err != null) {
- haxe_Log.trace(err,{ fileName : "src/server/cache/Cache.hx", lineNumber : 110, className : "server.cache.Cache", methodName : "getFreeDiskSpace"});
+ haxe_Log.trace(err,{ fileName : "src/server/cache/Cache.hx", lineNumber : 131, className : "server.cache.Cache", methodName : "getFreeDiskSpace"});
callback(_gthis.storageLimit);
return;
}
@@ -6421,7 +6765,7 @@ var server_cache_RawCache = function(main,cache) {
};
server_cache_RawCache.__name__ = true;
server_cache_RawCache.prototype = {
- cacheRawVideo: function(client,url,callback) {
+ cacheRawVideo: function(client,url,cb) {
var isM3U8 = url.indexOf(".m3u8") != -1;
var ext = isM3U8 ? "m3u8" : "mp4";
var matchName = new EReg("^([^:.]+)\\.(.+)","");
@@ -6434,49 +6778,94 @@ server_cache_RawCache.prototype = {
var outName = matchName.match(HxOverrides.substr(decodedUrl,decodedUrl.lastIndexOf("/") + 1,null)) ? matchName.matched(1) + ("." + ext) : "video." + ext;
outName = this.cache.getFreeFileName(outName);
if(this.cache.exists(outName)) {
- callback(outName);
+ var tmp = this.cache.getFileUrl(outName);
+ cb.onResolved(tmp);
+ cb.onComplete();
return;
}
- haxe_Log.trace("Caching " + url + " to " + outName + "...",{ fileName : "src/server/cache/RawCache.hx", lineNumber : 46, className : "server.cache.RawCache", methodName : "cacheRawVideo"});
- this.main.send(client,{ type : "Progress", progress : { type : "Caching", ratio : 0, data : outName}});
+ haxe_Log.trace("Caching " + url + " to " + outName + "...",{ fileName : "src/server/cache/RawCache.hx", lineNumber : 47, className : "server.cache.RawCache", methodName : "cacheRawVideo"});
+ var tmp = this.cache.getFileUrl(outName);
+ cb.onResolved(tmp);
if(isM3U8) {
- this.handleM3u8(client,url,outName,callback);
+ this.handleM3u8(client,url,outName,cb);
} else {
- this.handleMp4(client,url,outName,callback);
+ this.handleMp4(client,url,outName,cb);
}
}
- ,handleMp4: function(client,url,outName,callback) {
+ ,handleMp4: function(client,url,outName,cb) {
var _gthis = this;
var clientName = client.name;
+ var lastSentRatio = 0.0;
+ var canceled = false;
this.downloadFile(client,url,outName,function(downloaded,total) {
+ if(canceled) {
+ return;
+ }
var v = downloaded / total;
- _gthis.main.sendByName(clientName,{ type : "Progress", progress : { type : "Downloading", ratio : tools_MathTools.toFixed(v < 0 ? 0 : v > 1 ? 1 : v,4)}});
+ var ratio = v < 0 ? 0 : v > 1 ? 1 : v;
+ if(ratio - lastSentRatio < 0.01 && ratio < 1) {
+ return;
+ }
+ lastSentRatio = ratio;
+ var cb1 = cb;
+ var tmp = tools_MathTools.toFixed(ratio,4);
+ cb1.onProgress(tmp);
},function() {
- _gthis.cache.add(outName);
- callback(outName);
+ if(canceled) {
+ return;
+ }
+ _gthis.probeDuration(outName,function(duration) {
+ if(canceled) {
+ return;
+ }
+ if(duration > 0 && cb.onMetadata != null) {
+ cb.onMetadata(null,duration);
+ }
+ _gthis.cache.add(outName);
+ cb.onComplete();
+ });
},function(err) {
+ if(canceled) {
+ return;
+ }
_gthis.log(clientName,"Mp4 download failed: " + err);
- _gthis.cancelProgress(clientName);
+ cb.onError();
+ },function(cancel) {
+ if(cb.registerCancel == null) {
+ return;
+ }
+ cb.registerCancel(function() {
+ canceled = true;
+ cancel();
+ });
});
}
- ,handleM3u8: function(client,url,outName,callback) {
+ ,handleM3u8: function(client,url,outName,cb) {
var _gthis = this;
var clientName = client.name;
var useProxy = true;
+ var canceled = false;
+ if(cb.registerCancel != null) {
+ cb.registerCancel(function() {
+ canceled = true;
+ });
+ }
this.downloadM3u8Playlist(client,url,useProxy,function(playlist,totalSize,segments) {
+ if(canceled) {
+ return;
+ }
if(useProxy) {
totalSize = playlist.length;
}
if(!_gthis.cache.removeOlderCache(totalSize + _gthis.cache.freeSpaceBlock)) {
_gthis.log(clientName,_gthis.cache.notEnoughSpaceErrorText);
- _gthis.cancelProgress(clientName);
+ cb.onError();
return;
}
if(useProxy) {
- _gthis.main.sendByName(clientName,{ type : "Progress", progress : { type : "Caching", ratio : 1, data : outName}});
js_node_Fs.writeFileSync("" + _gthis.cache.cacheDir + "/" + outName,playlist);
_gthis.cache.add(outName);
- callback(outName);
+ cb.onComplete();
return;
}
var activeDownloads = 0;
@@ -6496,7 +6885,7 @@ server_cache_RawCache.prototype = {
}
segment[0].started = true;
activeDownloads += 1;
- haxe_Log.trace("download segment",{ fileName : "src/server/cache/RawCache.hx", lineNumber : 120, className : "server.cache.RawCache", methodName : "handleM3u8", customParams : [segment[0].i]});
+ haxe_Log.trace("download segment",{ fileName : "src/server/cache/RawCache.hx", lineNumber : 121, className : "server.cache.RawCache", methodName : "handleM3u8", customParams : [segment[0].i]});
_gthis.downloadFile(client,segment[0].url,segment[0].name,(function() {
return function(downloadedBytes,totalBytes) {
};
@@ -6506,12 +6895,12 @@ server_cache_RawCache.prototype = {
segment[0].completed = true;
downloaded += 1;
var progress = downloaded / segments.length;
- _gthis.main.sendByName(clientName,{ type : "Progress", progress : { type : "Downloading", ratio : progress < 0 ? 0 : progress > 1 ? 1 : progress}});
+ cb.onProgress(progress < 0 ? 0 : progress > 1 ? 1 : progress);
if(downloaded == segments.length) {
- haxe_Log.trace("All " + downloaded + "/" + segments.length + " segments downloaded",{ fileName : "src/server/cache/RawCache.hx", lineNumber : 140, className : "server.cache.RawCache", methodName : "handleM3u8"});
+ haxe_Log.trace("All " + downloaded + "/" + segments.length + " segments downloaded",{ fileName : "src/server/cache/RawCache.hx", lineNumber : 135, className : "server.cache.RawCache", methodName : "handleM3u8"});
js_node_Fs.writeFileSync("" + _gthis.cache.cacheDir + "/" + outName,playlist);
_gthis.cache.add(outName);
- callback(outName);
+ cb.onComplete();
} else {
downloadNextBatch();
}
@@ -6521,7 +6910,7 @@ server_cache_RawCache.prototype = {
activeDownloads -= 1;
downloaded += 1;
_gthis.log(clientName,"TS segment " + segment[0].i + " download failed: " + err);
- _gthis.cancelProgress(clientName);
+ cb.onError();
var _gthis1 = _gthis;
var result = new Array(segments.length);
var _g = 0;
@@ -6538,7 +6927,7 @@ server_cache_RawCache.prototype = {
downloadNextBatch();
},function(err) {
_gthis.log(clientName,"M3U8 processing failed: " + err);
- _gthis.cancelProgress(clientName);
+ cb.onError();
});
}
,request: function(url,options,callback) {
@@ -6599,6 +6988,7 @@ server_cache_RawCache.prototype = {
}
var req = _gthis.request(segments[0].url,{ method : "GET"},function(res) {
var tmp = Std.parseInt(res.headers["content-length"]);
+ res.destroy();
var totalSize = (tmp != null ? tmp : 0) * (segments.length + 1);
if(totalSize == 0) {
onError("Failed to get segment sizes: no content-length");
@@ -6619,8 +7009,9 @@ server_cache_RawCache.prototype = {
req.on("error",onError);
req.end();
}
- ,downloadFile: function(client,url,fileName,onProgress,onComplete,onError) {
- var file = js_node_Fs.createWriteStream("" + this.cache.cacheDir + "/" + fileName);
+ ,downloadFile: function(client,url,fileName,onProgress,onComplete,onError,onCancelable) {
+ var outPath = "" + this.cache.cacheDir + "/" + fileName;
+ var file = js_node_Fs.createWriteStream(outPath);
var req = this.request(url,{ method : "GET", headers : { "User-Agent" : "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537." + Std.random(100), "Accept" : "*/*"}},function(res) {
var total;
var tmp = Std.parseInt(res.headers["content-length"]);
@@ -6653,67 +7044,52 @@ server_cache_RawCache.prototype = {
file.destroy();
onError("Request failed: " + err);
});
+ if(onCancelable != null) {
+ onCancelable(function() {
+ req.destroy();
+ file.destroy();
+ if(sys_FileSystem.exists(outPath)) {
+ js_node_Fs.unlinkSync(outPath);
+ }
+ });
+ }
req.end();
}
+ ,probeDuration: function(fileName,callback) {
+ js_node_ChildProcess.execFile("ffprobe",["-v","error","-show_entries","format=duration","-of","default=noprint_wrappers=1:nokey=1","" + this.cache.cacheDir + "/" + fileName],function(err,stdout,_) {
+ if(err != null) {
+ callback(0);
+ return;
+ }
+ var duration = parseFloat(StringTools.trim(Std.string(stdout)));
+ callback(isNaN(duration) ? 0 : duration);
+ });
+ }
,cleanupFiles: function(files) {
var _g = 0;
while(_g < files.length) {
- var file = files[_g];
- ++_g;
- if(sys_FileSystem.exists(file)) {
- js_node_Fs.unlinkSync(file);
+ var path = "" + this.cache.cacheDir + "/" + files[_g++];
+ if(sys_FileSystem.exists(path)) {
+ js_node_Fs.unlinkSync(path);
}
}
}
,log: function(clientName,msg) {
this.cache.logByName(clientName,msg);
}
- ,cancelProgress: function(clientName) {
- this.main.sendByName(clientName,{ type : "Progress", progress : { type : "Canceled", ratio : 0}});
- }
,__class__: server_cache_RawCache
};
-var server_cache_YoutubeCache = function(main,cache) {
+var server_cache_YoutubeCache = function(main,cache,ytdlp) {
this.main = main;
this.cache = cache;
+ this.ytdlp = ytdlp;
};
server_cache_YoutubeCache.__name__ = true;
server_cache_YoutubeCache.prototype = {
- checkYtDeps: function() {
- try {
- js_node_ChildProcess.execSync("ffmpeg -version",{ stdio : "ignore", timeout : 5000});
- this.ytDlp = new (require('ytdlp-nodejs')).YtDlp();
- return true;
- } catch( _g ) {
- return false;
- }
- }
- ,checkUpdate: function() {
- this.ytDlp.execAsync("",{ updateTo : this.main.config.ytDlp.channel, onData : function(d) {
- haxe_Log.trace(d,{ fileName : "src/server/cache/YoutubeCache.hx", lineNumber : 36, className : "server.cache.YoutubeCache", methodName : "checkUpdate"});
- }}).catch(function(e) {
- haxe_Log.trace(e,{ fileName : "src/server/cache/YoutubeCache.hx", lineNumber : 39, className : "server.cache.YoutubeCache", methodName : "checkUpdate"});
- });
- }
- ,cleanYtInputFiles: function(prefix) {
- if(prefix == null) {
- prefix = "__tmp";
- }
- var names = js_node_Fs.readdirSync(this.cache.cacheDir);
- var _g = 0;
- while(_g < names.length) {
- var name = names[_g];
- ++_g;
- if(!StringTools.startsWith(name,prefix)) {
- continue;
- }
- this.cache.remove(name);
- }
- }
- ,cacheYoutubeVideo: function(client,url,callback) {
+ cacheYoutubeVideo: function(client,url,cb) {
var _gthis = this;
if(!this.cache.isYtReady) {
- haxe_Log.trace("Do `npm i https://github.com/RblSb/ytdlp-nodejs` to use cache feature (you also need to install `ffmpeg` to build mp4 from downloaded audio/video tracks).",{ fileName : "src/server/cache/YoutubeCache.hx", lineNumber : 53, className : "server.cache.YoutubeCache", methodName : "cacheYoutubeVideo"});
+ haxe_Log.trace("Do `npm i https://github.com/RblSb/ytdlp-nodejs` to use cache feature (you also need to install `ffmpeg` to build mp4 from downloaded audio/video tracks).",{ fileName : "src/server/cache/YoutubeCache.hx", lineNumber : 23, className : "server.cache.YoutubeCache", methodName : "cacheYoutubeVideo"});
return;
}
var clientName = client.name;
@@ -6722,9 +7098,13 @@ server_cache_YoutubeCache.prototype = {
this.log(clientName,"Error: youtube video id not found in url: " + url);
return;
}
+ url = "https://youtu.be/" + videoId;
var outName = videoId + ".mp4";
if(this.cache.exists(outName)) {
- callback(outName);
+ var cb1 = cb;
+ var tmp = this.cache.getFileUrl(outName);
+ cb1.onResolved(tmp);
+ cb.onComplete();
return;
}
var inVideoName = "__tmp-video-" + videoId;
@@ -6732,11 +7112,31 @@ server_cache_YoutubeCache.prototype = {
this.log(clientName,"Caching " + outName + " already in progress");
return;
}
- haxe_Log.trace("Caching " + url + " to " + outName + "...",{ fileName : "src/server/cache/YoutubeCache.hx", lineNumber : 85, className : "server.cache.YoutubeCache", methodName : "cacheYoutubeVideo"});
- this.main.sendByName(clientName,{ type : "Progress", progress : { type : "Caching", ratio : 0, data : outName}});
+ haxe_Log.trace("Caching " + url + " to " + outName + "...",{ fileName : "src/server/cache/YoutubeCache.hx", lineNumber : 58, className : "server.cache.YoutubeCache", methodName : "cacheYoutubeVideo"});
+ var cb1 = cb;
+ var tmp = this.cache.getFileUrl(outName);
+ cb1.onResolved(tmp);
var useCookies = false;
+ var lastSentRatio = 0.0;
+ var canceled = false;
+ var $process = null;
+ if(cb.registerCancel != null) {
+ cb.registerCancel(function() {
+ canceled = true;
+ if($process != null) {
+ $process.kill();
+ }
+ _gthis.ytdlp.cleanInputFiles(inVideoName);
+ });
+ }
var onGetInfo = function(info) {
- haxe_Log.trace("Get info with " + info.formats.length + " formats",{ fileName : "src/server/cache/YoutubeCache.hx", lineNumber : 98, className : "server.cache.YoutubeCache", methodName : "cacheYoutubeVideo"});
+ if(canceled) {
+ return;
+ }
+ if(cb.onMetadata != null) {
+ cb.onMetadata(info.title,info.duration);
+ }
+ haxe_Log.trace("Get info with " + info.formats.length + " formats",{ fileName : "src/server/cache/YoutubeCache.hx", lineNumber : 74, className : "server.cache.YoutubeCache", methodName : "cacheYoutubeVideo"});
var _this = info.formats;
var _g = [];
var _g1 = 0;
@@ -6794,7 +7194,7 @@ server_cache_YoutubeCache.prototype = {
if(tmp == null) {
_gthis.log(clientName,"Error: format with audio not found");
var _g = 0;
- while(_g < aformats.length) haxe_Log.trace(aformats[_g++],{ fileName : "src/server/cache/YoutubeCache.hx", lineNumber : 110, className : "server.cache.YoutubeCache", methodName : "cacheYoutubeVideo"});
+ while(_g < aformats.length) haxe_Log.trace(aformats[_g++],{ fileName : "src/server/cache/YoutubeCache.hx", lineNumber : 86, className : "server.cache.YoutubeCache", methodName : "cacheYoutubeVideo"});
return;
}
var _this = info.formats;
@@ -6823,7 +7223,7 @@ server_cache_YoutubeCache.prototype = {
} else {
_gthis.log(clientName,"Error: video format not found");
var _g1 = 0;
- while(_g1 < _g.length) haxe_Log.trace(_g[_g1++],{ fileName : "src/server/cache/YoutubeCache.hx", lineNumber : 120, className : "server.cache.YoutubeCache", methodName : "cacheYoutubeVideo"});
+ while(_g1 < _g.length) haxe_Log.trace(_g[_g1++],{ fileName : "src/server/cache/YoutubeCache.hx", lineNumber : 96, className : "server.cache.YoutubeCache", methodName : "cacheYoutubeVideo"});
return;
}
var ignoreQualities = [];
@@ -6847,8 +7247,8 @@ server_cache_YoutubeCache.prototype = {
var tmp2 = tmp.filesize;
var hasSpace = _gthis.cache.removeOlderCache(((tmp1 != null ? tmp1 : 0) + (tmp2 != null ? tmp2 : 0)) * 2 + _gthis.cache.freeSpaceBlock);
if(!hasSpace) {
- _gthis.cleanYtInputFiles(inVideoName);
- _gthis.cancelProgress(clientName);
+ _gthis.ytdlp.cleanInputFiles(inVideoName);
+ cb.onError();
_gthis.log(clientName,_gthis.cache.notEnoughSpaceErrorText);
}
if(!hasSpace) {
@@ -6870,13 +7270,13 @@ server_cache_YoutubeCache.prototype = {
videoSizeRatio = 1;
audioSizeRatio = 0;
}
- haxe_Log.trace(formatIds,{ fileName : "src/server/cache/YoutubeCache.hx", lineNumber : 153, className : "server.cache.YoutubeCache", methodName : "cacheYoutubeVideo", customParams : ["" + tools_MathTools.toFixed(totalSize / 1024 / 1024) + " MiB",tools_MathTools.toFixed(videoSizeRatio),tools_MathTools.toFixed(audioSizeRatio)]});
+ haxe_Log.trace(formatIds,{ fileName : "src/server/cache/YoutubeCache.hx", lineNumber : 129, className : "server.cache.YoutubeCache", methodName : "cacheYoutubeVideo", customParams : ["" + tools_MathTools.toFixed(totalSize / 1024 / 1024) + " MiB",tools_MathTools.toFixed(videoSizeRatio),tools_MathTools.toFixed(audioSizeRatio)]});
var videoRatioCache = 0.0;
var audioRatioCache = 0.0;
- var dlVideo = _gthis.ytDlp.downloadAsync(url,{ format : formatIds, output : "" + _gthis.cache.cacheDir + "/" + inVideoName, remuxVideo : "mp4", additionalOptions : ["--no-js-runtimes","--js-runtimes",_gthis.main.config.ytDlp.jsRuntime], cookies : useCookies ? _gthis.getCookiesPathOrNull() : null, forceIpv4 : true, socketTimeout : 2, extractorRetries : 0, onProgress : function(p) {
+ $process = _gthis.ytdlp.download(url,{ format : formatIds, output : "" + _gthis.cache.cacheDir + "/" + inVideoName, remuxVideo : "mp4", additionalOptions : _gthis.ytdlp.ytExtraOptions(), cookies : useCookies ? _gthis.ytdlp.getCookiesPathOrNull() : null, forceIpv4 : true, socketTimeout : 2, extractorRetries : 0},{ onProgress : function(p) {
var isFinished = p.status == "finished";
if(isFinished) {
- haxe_Log.trace("" + haxe_io_Path.withoutDirectory(p.filename) + " format file downloaded",{ fileName : "src/server/cache/YoutubeCache.hx", lineNumber : 171, className : "server.cache.YoutubeCache", methodName : "cacheYoutubeVideo"});
+ haxe_Log.trace("" + haxe_io_Path.withoutDirectory(p.filename) + " format file downloaded",{ fileName : "src/server/cache/YoutubeCache.hx", lineNumber : 147, className : "server.cache.YoutubeCache", methodName : "cacheYoutubeVideo"});
}
var ratio;
if(isFinished) {
@@ -6891,51 +7291,52 @@ server_cache_YoutubeCache.prototype = {
audioRatioCache = ratio;
}
ratio = videoRatioCache * videoSizeRatio + audioRatioCache * audioSizeRatio;
- _gthis.main.sendByName(clientName,{ type : "Progress", progress : { type : "Downloading", ratio : tools_MathTools.toFixed(ratio,4)}});
- }}).catch(function(err) {
- _gthis.cache.logWithAdmins(client,"Error during video download: " + err);
- _gthis.cleanYtInputFiles(inVideoName);
- _gthis.cancelProgress(clientName);
- });
- dlVideo.then(function(v) {
+ if(canceled) {
+ return;
+ }
+ if(ratio - lastSentRatio < 0.01 && ratio < 1) {
+ return;
+ }
+ lastSentRatio = ratio;
+ var cb1 = cb;
+ var $process = tools_MathTools.toFixed(ratio,4);
+ cb1.onProgress($process);
+ }, onComplete : function() {
+ if(canceled) {
+ _gthis.ytdlp.cleanInputFiles(inVideoName);
+ return;
+ }
var tmp = _gthis.cache.findFile(function(n) {
return StringTools.startsWith(n,inVideoName);
});
if(tmp == null) {
_gthis.cache.logWithAdmins(client,"Error: cannot find downloaded file with prefix " + inVideoName);
- _gthis.cancelProgress(clientName);
+ cb.onError();
return;
}
js_node_Fs.renameSync("" + _gthis.cache.cacheDir + "/" + tmp,"" + _gthis.cache.cacheDir + "/" + outName);
- _gthis.cleanYtInputFiles(inVideoName);
+ _gthis.ytdlp.cleanInputFiles(inVideoName);
_gthis.cache.add(outName);
- callback(outName);
- });
+ cb.onComplete();
+ }, onError : function(err) {
+ if(canceled) {
+ return;
+ }
+ _gthis.cache.logWithAdmins(client,"Error during video download: " + err);
+ _gthis.ytdlp.cleanInputFiles(inVideoName);
+ cb.onError();
+ }});
};
- this.getInfoAsync(url,useCookies).then(onGetInfo).catch(function(err) {
- haxe_Log.trace(err,{ fileName : "src/server/cache/YoutubeCache.hx", lineNumber : 215, className : "server.cache.YoutubeCache", methodName : "cacheYoutubeVideo"});
+ this.ytdlp.getInfoAsync(url,useCookies).then(onGetInfo).catch(function(err) {
+ haxe_Log.trace(err,{ fileName : "src/server/cache/YoutubeCache.hx", lineNumber : 193, className : "server.cache.YoutubeCache", methodName : "cacheYoutubeVideo"});
useCookies = true;
- return _gthis.getInfoAsync(url,useCookies).then(onGetInfo).catch(function(err) {
- _gthis.cleanYtInputFiles(inVideoName);
- _gthis.cancelProgress(clientName);
+ return _gthis.ytdlp.getInfoAsync(url,useCookies).then(onGetInfo).catch(function(err) {
+ _gthis.ytdlp.cleanInputFiles(inVideoName);
+ cb.onError();
_gthis.log(clientName,"" + err);
});
});
}
- ,getInfoAsync: function(url,useCookies) {
- if(useCookies == null) {
- useCookies = false;
- }
- return this.ytDlp.getInfoAsync(url,{ cookies : useCookies ? this.getCookiesPathOrNull() : null, additionalOptions : ["--no-js-runtimes","--js-runtimes",this.main.config.ytDlp.jsRuntime]});
- }
- ,getCookiesPathOrNull: function() {
- var cookiesPath = "" + this.main.userDir + "/cookies.txt";
- if(sys_FileSystem.exists(cookiesPath)) {
- return cookiesPath;
- } else {
- return null;
- }
- }
,getBestYoutubeVideoFormat: function(formats,ignoreQualities) {
var qPriority = [1080,720,480,360,240,144];
if(ignoreQualities != null) {
@@ -6984,11 +7385,230 @@ server_cache_YoutubeCache.prototype = {
,log: function(clientName,msg) {
this.cache.logByName(clientName,msg);
}
- ,cancelProgress: function(clientName) {
- this.main.sendByName(clientName,{ type : "Progress", progress : { type : "Canceled", ratio : 0}});
- }
,__class__: server_cache_YoutubeCache
};
+var server_cache_YtdlpCache = function(main,cache) {
+ this.main = main;
+ this.cache = cache;
+};
+server_cache_YtdlpCache.__name__ = true;
+server_cache_YtdlpCache.prototype = {
+ checkYtDeps: function() {
+ try {
+ js_node_ChildProcess.execSync("ffmpeg -version",{ stdio : "ignore", timeout : 5000});
+ this.ytDlp = new (require('ytdlp-nodejs')).YtDlp();
+ return true;
+ } catch( _g ) {
+ return false;
+ }
+ }
+ ,checkUpdate: function() {
+ this.ytDlp.execAsync("",{ updateTo : this.main.config.ytDlp.channel, onData : function(d) {
+ haxe_Log.trace(d,{ fileName : "src/server/cache/YtdlpCache.hx", lineNumber : 43, className : "server.cache.YtdlpCache", methodName : "checkUpdate"});
+ }}).catch(function(e) {
+ haxe_Log.trace(e,{ fileName : "src/server/cache/YtdlpCache.hx", lineNumber : 46, className : "server.cache.YtdlpCache", methodName : "checkUpdate"});
+ });
+ }
+ ,cleanInputFiles: function(prefix) {
+ if(prefix == null) {
+ prefix = "__tmp";
+ }
+ var names = js_node_Fs.readdirSync(this.cache.cacheDir);
+ var _g = 0;
+ while(_g < names.length) {
+ var name = names[_g];
+ ++_g;
+ if(!StringTools.startsWith(name,prefix)) {
+ continue;
+ }
+ this.cache.remove(name);
+ }
+ }
+ ,getInfoAsync: function(url,useCookies) {
+ if(useCookies == null) {
+ useCookies = false;
+ }
+ return this.ytDlp.getInfoAsync(url,{ cookies : useCookies ? this.getCookiesPathOrNull() : null, additionalOptions : this.ytExtraOptions()});
+ }
+ ,getCookiesPathOrNull: function() {
+ var cookiesPath = "" + this.main.userDir + "/cookies.txt";
+ if(sys_FileSystem.exists(cookiesPath)) {
+ return cookiesPath;
+ } else {
+ return null;
+ }
+ }
+ ,ytExtraOptions: function() {
+ return ["--no-js-runtimes","--js-runtimes",this.main.config.ytDlp.jsRuntime];
+ }
+ ,checkUrlSupported: function(url,callback) {
+ var $process = this.ytDlp.exec(url,{ useExtractors : ["default","-generic"], simulate : true, quiet : true, socketTimeout : 5, extractorRetries : 0});
+ var done = false;
+ $process.on("close",function(code,_signal) {
+ if(!done) {
+ done = true;
+ callback(code == 0);
+ }
+ });
+ $process.on("error",function(_err) {
+ if(!done) {
+ done = true;
+ callback(false);
+ }
+ });
+ return $process;
+ }
+ ,download: function(url,options,handlers) {
+ var $process = this.ytDlp.exec(url,options);
+ var stderr = "";
+ var done = false;
+ $process.stderr.on("data",function(d) {
+ stderr += Std.string(d);
+ return stderr;
+ });
+ $process.on("progress",function(p) {
+ handlers.onProgress(p);
+ });
+ $process.on("close",function(code,_signal) {
+ if(done) {
+ return;
+ }
+ done = true;
+ if(code == 0) {
+ handlers.onComplete();
+ } else {
+ handlers.onError("yt-dlp exited with code " + code + ": " + stderr);
+ }
+ });
+ $process.on("error",function(err) {
+ if(done) {
+ return;
+ }
+ done = true;
+ handlers.onError("Failed to start yt-dlp process: " + Std.string(err));
+ });
+ return $process;
+ }
+ ,cacheVideo: function(client,url,cb) {
+ var _gthis = this;
+ var clientName = client.name;
+ var outName = this.deriveOutName(url);
+ haxe_Log.trace("Caching " + url + " to " + outName + "...",{ fileName : "src/server/cache/YtdlpCache.hx", lineNumber : 128, className : "server.cache.YtdlpCache", methodName : "cacheVideo"});
+ var cb1 = cb;
+ var tmp = this.cache.getFileUrl(outName);
+ cb1.onResolved(tmp);
+ var inName = "__tmp-" + Std.random(16777215) + "-" + haxe_io_Path.withoutExtension(outName);
+ var canceled = false;
+ var $process = null;
+ if(cb.registerCancel != null) {
+ cb.registerCancel(function() {
+ canceled = true;
+ if($process != null) {
+ $process.kill();
+ }
+ _gthis.cleanInputFiles(inName);
+ });
+ }
+ var useCookies = false;
+ var lastSentRatio = 0.0;
+ var onGetInfo = function(info) {
+ if(canceled) {
+ return;
+ }
+ if(cb.onMetadata != null) {
+ cb.onMetadata(info.title,info.duration);
+ }
+ if(!_gthis.cache.removeOlderCache(_gthis.estimateSize(info) * 2 + _gthis.cache.freeSpaceBlock)) {
+ _gthis.cleanInputFiles(inName);
+ cb.onError();
+ _gthis.log(clientName,_gthis.cache.notEnoughSpaceErrorText);
+ return;
+ }
+ $process = _gthis.download(url,{ output : "" + _gthis.cache.cacheDir + "/" + inName, remuxVideo : "mp4", additionalOptions : _gthis.ytExtraOptions(), cookies : useCookies ? _gthis.getCookiesPathOrNull() : null, forceIpv4 : true, socketTimeout : 5, extractorRetries : 0},{ onProgress : function(p) {
+ if(canceled) {
+ return;
+ }
+ var ratio;
+ if(p.status == "finished") {
+ ratio = 1.0;
+ } else {
+ var v = p.downloaded / p.total;
+ ratio = v < 0 ? 0 : v > 1 ? 1 : v;
+ }
+ if(ratio - lastSentRatio < 0.01 && ratio < 1) {
+ return;
+ }
+ lastSentRatio = ratio;
+ var cb1 = cb;
+ var $process = tools_MathTools.toFixed(ratio,4);
+ cb1.onProgress($process);
+ }, onComplete : function() {
+ if(canceled) {
+ _gthis.cleanInputFiles(inName);
+ return;
+ }
+ var tmp = _gthis.cache.findFile(function(n) {
+ return StringTools.startsWith(n,inName);
+ });
+ if(tmp == null) {
+ _gthis.cache.logWithAdmins(client,"Error: cannot find downloaded file with prefix " + inName);
+ cb.onError();
+ return;
+ }
+ js_node_Fs.renameSync("" + _gthis.cache.cacheDir + "/" + tmp,"" + _gthis.cache.cacheDir + "/" + outName);
+ _gthis.cleanInputFiles(inName);
+ _gthis.cache.add(outName);
+ cb.onComplete();
+ }, onError : function(err) {
+ if(canceled) {
+ return;
+ }
+ _gthis.cache.logWithAdmins(client,"Error during video download: " + err);
+ _gthis.cleanInputFiles(inName);
+ cb.onError();
+ }});
+ };
+ this.getInfoAsync(url,useCookies).then(onGetInfo).catch(function(err) {
+ if(canceled) {
+ return;
+ }
+ useCookies = true;
+ _gthis.getInfoAsync(url,useCookies).then(onGetInfo).catch(function(err) {
+ _gthis.cleanInputFiles(inName);
+ cb.onError();
+ _gthis.log(clientName,"" + err);
+ });
+ });
+ }
+ ,deriveOutName: function(url) {
+ var decoded;
+ try {
+ decoded = decodeURIComponent(url.split("+").join(" "));
+ } catch( _g ) {
+ decoded = url;
+ }
+ var last = HxOverrides.substr(decoded,decoded.lastIndexOf("/") + 1,null);
+ var q = last.indexOf("?");
+ if(q != -1) {
+ last = HxOverrides.substr(last,0,q);
+ }
+ last = haxe_io_Path.withoutExtension(last);
+ if(last == "") {
+ last = "video";
+ }
+ return this.cache.getFreeFileName("" + last + ".mp4");
+ }
+ ,estimateSize: function(info) {
+ var d = info;
+ var tmp = d.filesize_approx;
+ var tmp1 = tmp != null ? tmp : d.filesize;
+ return (tmp1 != null ? tmp1 : 0) | 0;
+ }
+ ,log: function(clientName,msg) {
+ this.cache.logByName(clientName,msg);
+ }
+ ,__class__: server_cache_YtdlpCache
+};
var sys_FileSystem = function() { };
sys_FileSystem.__name__ = true;
sys_FileSystem.exists = function(path) {
send patches to the email below
yukais@pinapelz.com
include the subject [PATCH repo_name]
pinapelz.com
homepage