Mega Update

- Add Extender functions in some places. Hopefully will add in all functions after more rewriting.
- Add Backblaze B2 uploading support
- Add support for managing cloud storage space used
- put all cloud video management functions in one library file using Extender
- separate uses of "s.s". s.s = JSON.stringify again and API calls with s.s will use "s.prettyPrint"
- move ffmpeg init functions
- rename s.beat to better reflect purpose
merge-requests/63/head
Moe 2018-09-30 15:44:04 -07:00
parent afbd2f7172
commit a3744787d9
12 changed files with 862 additions and 297 deletions

View File

@ -16,8 +16,10 @@ s = {
totalmem : os.totalmem(),
//Check Platform
platform : os.platform(),
//JSON stringify short-hand
s : JSON.stringify,
//Pretty Print JSON
s : function(obj){return JSON.stringify(obj,null,3)},
prettyPrint : function(obj){return JSON.stringify(obj,null,3)},
//Check if Windows
isWin : (process.platform === 'win32' || process.platform === 'win64'),
//UTC Offset
@ -69,6 +71,8 @@ loadLib('ffmpeg')(s,config,function(){
loadLib('health')(s,config,lang,io)
//cluster module
loadLib('childNode')(s,config,lang,io)
//cloud uploaders : amazon s3, webdav, blackblaze b2..
loadLib('cloudUploaders')(s,config,lang)
//on-start actions
loadLib('startup')(s,config,lang)
})

View File

@ -190,16 +190,22 @@
"Account Info": "Account Info",
"blankPassword": "Leave blank to keep same password",
"2-Factor Authentication": "2-Factor Authentication",
"Use Max Storage Amount": "Use Max Storage Amount",
"Max Storage Amount": "Max Storage Amount <small>in Megabytes</small>",
"Number of Days to keep": "Number of Days to keep",
"Monitor Groups": "Monitor Groups",
"Group Name": "Group Name",
"WebDAV": "WebDAV",
"Backblaze B2": "Backblaze B2",
"Backblaze Error": "Backblaze Error",
"Could not create Bucket.": "Could not create Bucket.",
"Amazon S3": "Amazon S3",
"Save Links to Database": "Save Links to Database",
"Bucket": "Bucket",
"Region": "Region",
"Amazon S3 Upload Error": "Amazon S3 Upload Error",
"accountId": "Account ID",
"applicationKey": "Application Key",
"aws_accessKeyId": "Access Key Id",
"aws_secretAccessKey": "Secret Access Key",
"Discord Bot": "Discord Bot",

428
libs/cloudUploaders.js Normal file
View File

@ -0,0 +1,428 @@
var fs = require('fs');
var exec = require('child_process').exec;
var spawn = require('child_process').spawn;
var webdav = require("webdav-fs");
module.exports = function(s,config,lang){
// WebDAV
var beforeAccountSaveForWebDav = function(d){
//d = save event
d.form.details.use_webdav=d.d.use_webdav
}
var cloudDiskUseStartupForWebDav = function(group,userDetails){
group.cloudDiskUse['webdav'].name = 'WebDAV'
group.cloudDiskUse['webdav'].sizeLimitCheck = (userDetails.use_webdav_size_limit === '1')
if(!userDetails.webdav_size_limit || userDetails.webdav_size_limit === ''){
group.cloudDiskUse['webdav'].sizeLimit = 10000
}else{
group.cloudDiskUse['webdav'].sizeLimit = parseFloat(userDetails.webdav_size_limit)
}
}
var loadWebDavForUser = function(e){
// e = user
var ar = JSON.parse(e.details);
//owncloud/webdav
if(!s.group[e.ke].webdav &&
ar.webdav_user&&
ar.webdav_user!==''&&
ar.webdav_pass&&
ar.webdav_pass!==''&&
ar.webdav_url&&
ar.webdav_url!==''
){
if(!ar.webdav_dir||ar.webdav_dir===''){
ar.webdav_dir='/'
}
ar.webdav_dir = s.checkCorrectPathEnding(ar.webdav_dir)
s.group[e.ke].webdav = webdav(
ar.webdav_url,
ar.webdav_user,
ar.webdav_pass
)
}
}
var unloadWebDavForUser = function(user){
s.group[user.ke].webdav = null
}
var deleteVideoFromWebDav = function(e,video,callback){
// e = user
try{
var videoDetails = JSON.parse(video.details)
}catch(err){
var videoDetails = video.details
}
if(!videoDetails.location){
var prefix = s.addUserPassToUrl(s.checkCorrectPathEnding(s.group[e.ke].init.webdav_url),s.group[e.ke].init.webdav_user,s.group[e.ke].init.webdav_pass)
videoDetails.location = video.href.replace(prefix,'')
}
s.group[e.ke].webdav.unlink(videoDetails.location, function(err) {
if (err) console.log(videoDetails.location,err)
callback()
})
}
var uploadVideoToWebDav = function(e,k){
//e = video object
//k = temporary values
if(!k)k={};
//cloud saver - webdav
var wfs = s.group[e.ke].webdav
if(wfs && s.group[e.ke].init.use_webdav !== '0' && s.group[e.ke].init.webdav_save === "1"){
var webdavUploadDir = s.group[e.ke].init.webdav_dir+e.ke+'/'+e.mid+'/'
var startWebDavUpload = function(){
s.group[e.ke].mon[e.id].webdavDirExist = true
var wfsWriteStream =
fs.createReadStream(k.dir + k.filename).pipe(wfs.createWriteStream(webdavUploadDir + k.filename))
if(s.group[e.ke].init.webdav_log === '1'){
var webdavRemoteUrl = s.addUserPassToUrl(s.checkCorrectPathEnding(s.group[e.ke].init.webdav_url),s.group[e.ke].init.webdav_user,s.group[e.ke].init.webdav_pass) + s.group[e.ke].init.webdav_dir + e.ke + '/'+e.mid+'/'+k.filename
var save = [
e.mid,
e.ke,
k.startTime,
1,
s.s({
type : 'webdav',
location : webdavUploadDir + k.filename
}),
k.filesize,
k.endTime,
webdavRemoteUrl
]
s.sqlQuery('INSERT INTO `Cloud Videos` (mid,ke,time,status,details,size,end,href) VALUES (?,?,?,?,?,?,?,?)',save)
s.setCloudDiskUsedForGroup(e,{
amount : k.filesizeMB,
storageType : 'webdav'
})
s.purgeCloudDiskForGroup(e,'webdav')
}
}
if(s.group[e.ke].mon[e.id].webdavDirExist !== true){
//check if webdav dir exist
var parentPoint = 0
var webDavParentz = webdavUploadDir.split('/')
var webDavParents = []
webDavParentz.forEach(function(v){
if(v && v !== '')webDavParents.push(v)
})
var stitchPieces = './'
var lastParentCheck = function(){
++parentPoint
if(parentPoint === webDavParents.length){
startWebDavUpload()
}
checkPathPiece(webDavParents[parentPoint])
}
var checkPathPiece = function(pathPiece){
if(pathPiece && pathPiece !== ''){
stitchPieces += pathPiece + '/'
wfs.stat(stitchPieces, function(error, stats) {
if(error){
reply = {
status : error.status,
msg : lang.WebdavErrorTextTryCreatingDir,
dir : stitchPieces,
}
s.log(e,{type:lang['Webdav Error'],msg:reply})
wfs.mkdir(stitchPieces, function(error) {
if(error){
reply = {
status : error.status,
msg : lang.WebdavErrorTextCreatingDir,
dir : stitchPieces,
}
s.log(e,{type:lang['Webdav Error'],msg:reply})
}else{
lastParentCheck()
}
})
}else{
lastParentCheck()
}
})
}else{
++parentPoint
}
}
checkPathPiece(webDavParents[0])
}else{
startWebDavUpload()
}
}
}
//Amazon S3
var beforeAccountSaveForAmazonS3 = function(d){
//d = save event
d.form.details.use_aws_s3=d.d.use_aws_s3
}
var cloudDiskUseStartupForAmazonS3 = function(group,userDetails){
group.cloudDiskUse['s3'].name = 'Amazon S3'
group.cloudDiskUse['s3'].sizeLimitCheck = (userDetails.use_aws_s3_size_limit === '1')
if(!userDetails.aws_s3_size_limit || userDetails.aws_s3_size_limit === ''){
group.cloudDiskUse['s3'].sizeLimit = 10000
}else{
group.cloudDiskUse['s3'].sizeLimit = parseFloat(userDetails.aws_s3_size_limit)
}
}
var loadAmazonS3ForUser = function(e){
// e = user
var ar = JSON.parse(e.details);
//Amazon S3
if(!s.group[e.ke].aws &&
!s.group[e.ke].aws_s3 &&
ar.aws_s3 !== '0' &&
ar.aws_accessKeyId !== ''&&
ar.aws_secretAccessKey &&
ar.aws_secretAccessKey !== ''&&
ar.aws_region &&
ar.aws_region !== ''&&
ar.aws_s3_bucket !== ''
){
if(!ar.aws_s3_dir || ar.aws_s3_dir === '/'){
ar.aws_s3_dir = ''
}
if(ar.aws_s3_dir !== ''){
ar.aws_s3_dir = s.checkCorrectPathEnding(ar.aws_s3_dir)
}
s.group[e.ke].aws = new require("aws-sdk")
s.group[e.ke].aws.config = new s.group[e.ke].aws.Config({
accessKeyId: ar.aws_accessKeyId,
secretAccessKey: ar.aws_secretAccessKey,
region: ar.aws_region
})
s.group[e.ke].aws_s3 = new s.group[e.ke].aws.S3();
}
}
var unloadAmazonS3ForUser = function(user){
s.group[user.ke].aws = null
s.group[user.ke].aws_s3 = null
}
var deleteVideoFromAmazonS3 = function(e,video,callback){
// e = user
try{
var videoDetails = JSON.parse(video.details)
}catch(err){
var videoDetails = video.details
}
if(!videoDetails.location){
videoDetails.location = video.href.split('.amazonaws.com')[1]
}
s.group[e.ke].aws_s3.deleteObject({
Bucket: s.group[e.ke].init.aws_s3_bucket,
Key: videoDetails.location,
}, function(err, data) {
if (err) console.log(err);
callback()
});
}
var uploadVideoToAmazonS3 = function(e,k){
//e = video object
//k = temporary values
if(!k)k={};
//cloud saver - amazon s3
if(s.group[e.ke].aws_s3 && s.group[e.ke].init.use_aws_s3 !== '0' && s.group[e.ke].init.aws_s3_save === '1'){
var fileStream = fs.createReadStream(k.dir+k.filename);
fileStream.on('error', function (err) {
console.error(err)
})
var saveLocation = s.group[e.ke].init.aws_s3_dir+e.ke+'/'+e.mid+'/'+k.filename
s.group[e.ke].aws_s3.upload({
Bucket: s.group[e.ke].init.aws_s3_bucket,
Key: saveLocation,
Body:fileStream,
ACL:'public-read'
},function(err,data){
if(err){
s.log(e,{type:lang['Amazon S3 Upload Error'],msg:err})
}
if(s.group[e.ke].init.aws_s3_log === '1' && data && data.Location){
var save = [
e.mid,
e.ke,
k.startTime,
1,
s.s({
type : 's3',
location : saveLocation
}),
k.filesize,
k.endTime,
data.Location
]
s.sqlQuery('INSERT INTO `Cloud Videos` (mid,ke,time,status,details,size,end,href) VALUES (?,?,?,?,?,?,?,?)',save)
s.setCloudDiskUsedForGroup(e,{
amount : k.filesizeMB,
storageType : 's3'
})
s.purgeCloudDiskForGroup(e,'s3')
}
})
}
}
//Backblaze B2
var beforeAccountSaveForBackblazeB2 = function(d){
//d = save event
d.form.details.use_aws_s3=d.d.use_bb_b2
}
var cloudDiskUseStartupForBackblazeB2 = function(group,userDetails){
group.cloudDiskUse['b2'].name = 'Backblaze B2'
group.cloudDiskUse['b2'].sizeLimitCheck = (userDetails.use_bb_b2_size_limit === '1')
if(!userDetails.bb_b2_size_limit || userDetails.bb_b2_size_limit === ''){
group.cloudDiskUse['b2'].sizeLimit = 10000
}else{
group.cloudDiskUse['b2'].sizeLimit = parseFloat(userDetails.bb_b2_size_limit)
}
}
var loadBackblazeB2ForUser = function(e){
var ar = JSON.parse(e.details);
try{
var B2 = require('backblaze-b2')
if(!s.group[e.ke].bb_b2 &&
ar.bb_b2_accountId &&
ar.bb_b2_accountId !=='' &&
ar.bb_b2_applicationKey &&
ar.bb_b2_applicationKey !=='' &&
ar.bb_b2_bucket &&
ar.bb_b2_bucket !== ''
){
if(!ar.bb_b2_dir || ar.bb_b2_dir === '/'){
ar.bb_b2_dir = ''
}
if(ar.bb_b2_dir !== ''){
ar.bb_b2_dir = s.checkCorrectPathEnding(ar.bb_b2_dir)
}
var b2 = new B2({
accountId: ar.bb_b2_accountId,
applicationKey: ar.bb_b2_applicationKey
})
s.group[e.ke].bb_b2 = b2
var backblazeErr = function(err){
// console.log(err)
s.log({mid:'$USER',ke:e.ke},{type:lang['Backblaze Error'],msg:err.data})
}
b2.authorize().then(function(resp){
s.group[e.ke].bb_b2_downloadUrl = resp.data.downloadUrl
b2.listBuckets().then(function(resp){
var buckets = resp.data.buckets
var bucketN = -2
buckets.forEach(function(item,n){
if(item.bucketName === ar.bb_b2_bucket){
bucketN = n
}
})
if(bucketN > -1){
s.group[e.ke].bb_b2_bucketId = buckets[bucketN].bucketId
}else{
b2.createBucket(
ar.bb_b2_bucket,
'allPublic'
).then(function(resp){
s.group[e.ke].bb_b2_bucketId = resp.data.bucketId
}).catch(backblazeErr)
}
}).catch(backblazeErr)
}).catch(backblazeErr)
}
}catch(err){
console.log(err)
}
}
var unloadBackblazeB2ForUser = function(user){
s.group[user.ke].bb_b2 = null
}
var deleteVideoFromBackblazeB2 = function(e,video,callback){
// e = user
try{
var videoDetails = JSON.parse(video.details)
}catch(err){
var videoDetails = video.details
}
s.group[e.ke].bb_b2.deleteFileVersion({
fileId: videoDetails.fileId,
fileName: videoDetails.fileName
}).then(function(resp){
// console.log('deleteFileVersion',resp.data)
}).catch(function(err){
console.log('deleteFileVersion',err)
})
}
var uploadVideoToBackblazeB2 = function(e,k){
//e = video object
//k = temporary values
if(!k)k={};
//cloud saver - Backblaze B2
if(s.group[e.ke].bb_b2 && s.group[e.ke].init.use_bb_b2 !== '0' && s.group[e.ke].init.bb_b2_save === '1'){
var backblazeErr = function(err){
// console.log(err)
s.log({mid:'$USER',ke:e.ke},{type:lang['Backblaze Error'],msg:err.data})
}
fs.readFile(k.dir+k.filename,function(err,data){
var backblazeSavePath = s.group[e.ke].init.bb_b2_dir+e.ke+'/'+e.mid+'/'+k.filename
var getUploadUrl = function(bucketId,callback){
s.group[e.ke].bb_b2.getUploadUrl(bucketId).then(function(resp){
callback(resp.data)
}).catch(backblazeErr)
}
getUploadUrl(s.group[e.ke].bb_b2_bucketId,function(req){
s.group[e.ke].bb_b2.uploadFile({
uploadUrl: req.uploadUrl,
uploadAuthToken: req.authorizationToken,
filename: backblazeSavePath,
data: data,
onUploadProgress: null
}).then(function(resp){
if(s.group[e.ke].init.bb_b2_log === '1' && resp.data.fileId){
var backblazeDownloadUrl = s.group[e.ke].bb_b2_downloadUrl + '/file/' + s.group[e.ke].init.bb_b2_bucket + '/' + backblazeSavePath
var save = [
e.mid,
e.ke,
k.startTime,
1,
s.s({
type : 'b2',
bucketId : resp.data.bucketId,
fileId : resp.data.fileId,
fileName : resp.data.fileName
}),
k.filesize,
k.endTime,
backblazeDownloadUrl
]
s.sqlQuery('INSERT INTO `Cloud Videos` (mid,ke,time,status,details,size,end,href) VALUES (?,?,?,?,?,?,?,?)',save)
s.setCloudDiskUsedForGroup(e,{
amount : k.filesizeMB,
storageType : 'b2'
})
s.purgeCloudDiskForGroup(e,'b2')
}
}).catch(backblazeErr)
})
})
}
}
//add the extenders
//webdav
s.loadGroupAppExtender(loadWebDavForUser)
s.unloadGroupAppExtender(unloadWebDavForUser)
s.insertCompletedVideoExtender(uploadVideoToWebDav)
s.deleteVideoFromCloudExtensions['webdav'] = deleteVideoFromWebDav
s.cloudDiskUseStartupExtensions['webdav'] = cloudDiskUseStartupForWebDav
s.beforeAccountSave(beforeAccountSaveForWebDav)
s.onAccountSave(cloudDiskUseStartupForWebDav)
s.cloudDisksLoader('webdav')
//amazon s3
s.loadGroupAppExtender(loadAmazonS3ForUser)
s.unloadGroupAppExtender(unloadAmazonS3ForUser)
s.insertCompletedVideoExtender(uploadVideoToAmazonS3)
s.deleteVideoFromCloudExtensions['s3'] = deleteVideoFromAmazonS3
s.cloudDiskUseStartupExtensions['s3'] = cloudDiskUseStartupForAmazonS3
s.beforeAccountSave(beforeAccountSaveForAmazonS3)
s.onAccountSave(cloudDiskUseStartupForAmazonS3)
s.cloudDisksLoader('s3')
//backblaze b2
s.loadGroupAppExtender(loadBackblazeB2ForUser)
s.unloadGroupAppExtender(unloadBackblazeB2ForUser)
s.insertCompletedVideoExtender(uploadVideoToBackblazeB2)
s.deleteVideoFromCloudExtensions['b2'] = deleteVideoFromBackblazeB2
s.cloudDiskUseStartupExtensions['b2'] = cloudDiskUseStartupForBackblazeB2
s.beforeAccountSave(beforeAccountSaveForBackblazeB2)
s.onAccountSave(cloudDiskUseStartupForBackblazeB2)
s.cloudDisksLoader('b2')
}

View File

@ -84,18 +84,6 @@ module.exports = function(s,config,callback){
failback()
}
}
//ffmpeg location
if(!config.ffmpegDir){
windowsFfmpegCheck(function(){
unixFfmpegCheck(function(){
ffbinaryCheck(function(){
ffmpegStaticCheck(function(){
console.log('No FFmpeg found.')
})
})
})
})
}
s.splitForFFPMEG = function (ffmpegCommandAsString) {
//this function ignores spaces inside quotes.
return ffmpegCommandAsString.match(/\\?.|^$/g).reduce((p, c) => {
@ -846,6 +834,17 @@ module.exports = function(s,config,callback){
x.ffmpegCommandString = s.splitForFFPMEG(x.ffmpegCommandString.replace(/\s+/g,' ').trim())
return spawn(config.ffmpegDir,x.ffmpegCommandString,{detached: true,stdio:x.stdioPipes});
}
if(!config.ffmpegDir){
windowsFfmpegCheck(function(){
unixFfmpegCheck(function(){
ffbinaryCheck(function(){
ffmpegStaticCheck(function(){
console.log('No FFmpeg found.')
})
})
})
})
}
if(downloadingFfmpeg === false){
//not downloading ffmpeg
completeFfmpegCheck()

View File

@ -13,11 +13,11 @@ module.exports = function(s,config,lang,io){
s.tx({f:'diskUsed',size:s.group[e.ke].usedSpace,limit:s.group[e.ke].sizeLimit},'GRP_'+e.ke);
}
}
s.beat=function(){
setTimeout(s.beat, 8000);
s.heartBeat = function(){
setTimeout(s.heartBeat, 8000);
io.sockets.emit('ping',{beat:1});
}
s.beat();
s.heartBeat()
s.cpuUsage = function(callback){
k={}
switch(s.platform){

View File

@ -32,6 +32,29 @@ module.exports = function(s,config,lang){
}
})
}
var loadDiscordBotForUser = function(user){
ar=JSON.parse(user.details);
//discordbot
if(!s.group[user.ke].discordBot &&
config.discordBot === true &&
ar.discordbot === '1' &&
ar.discordbot_token !== ''
){
s.group[user.ke].discordBot = new Discord.Client()
s.group[user.ke].discordBot.on('ready', () => {
console.log(`${user.mail} : Discord Bot Logged in as ${s.group[user.ke].discordBot.user.tag}!`)
})
s.group[user.ke].discordBot.login(ar.discordbot_token)
}
}
var unloadDiscordBotForUser = function(user){
if(s.group[user.ke].discordBot && s.group[user.ke].discordBot.destroy){
s.group[user.ke].discordBot.destroy()
delete(s.group[user.ke].discordBot)
}
}
s.loadGroupAppExtender(loadDiscordBotForUser)
s.unloadGroupAppExtender(unloadDiscordBotForUser)
}catch(err){
console.log('Could not start Discord bot, please run "npm install discord.js" inside the Shinobi folder.')
s.discordMsg = function(){}

View File

@ -597,13 +597,14 @@ module.exports = function(s,config,lang,io){
}
///unchangeable from client side, so reset them in case they did.
d.form.details=JSON.parse(d.form.details)
s.beforeAccountSaveExtensions.forEach(function(extender){
extender(d)
})
//admin permissions
d.form.details.permissions=d.d.permissions
d.form.details.edit_size=d.d.edit_size
d.form.details.edit_days=d.d.edit_days
d.form.details.use_admin=d.d.use_admin
d.form.details.use_webdav=d.d.use_webdav
d.form.details.use_aws_s3=d.d.use_aws_s3
d.form.details.use_ldap=d.d.use_ldap
//check
if(d.d.edit_days=="0"){
@ -624,7 +625,7 @@ module.exports = function(s,config,lang,io){
if(d.d.days){d.form.details.days=d.d.days;}
delete(d.form.details.mon_groups)
}
var newSize = d.form.details.size
var newSize = d.form.details.size || 10000
d.form.details=JSON.stringify(d.form.details)
///
d.set=[],d.ar=[];
@ -637,14 +638,15 @@ module.exports = function(s,config,lang,io){
d.ar.push(d.ke),d.ar.push(d.uid);
s.sqlQuery('UPDATE Users SET '+d.set.join(',')+' WHERE ke=? AND uid=?',d.ar,function(err,r){
if(!d.d.sub){
var user = Object.assign(d.form,{ke : d.ke})
var userDetails = JSON.parse(d.form.details)
s.group[d.ke].sizeLimit = parseFloat(newSize)
s.group[d.ke].webdav = null
s.group[d.ke].aws = null
s.group[d.ke].aws_s3 = null
if(s.group[d.ke].discordBot && s.group[d.ke].discordBot.destroy){
s.group[d.ke].discordBot.destroy()
delete(s.group[d.ke].discordBot)
}
s.onAccountSaveExtensions.forEach(function(extender){
extender(s.group[d.ke],userDetails)
})
s.unloadGroupAppExtensions.forEach(function(extender){
extender(user)
})
s.loadGroupApps(d)
}
tx({f:'user_settings_change',uid:d.uid,ke:d.ke,form:d.form});

View File

@ -27,31 +27,85 @@ module.exports = function(s,config,lang,io){
callback()
})
}
var loadDiskUseForUser = function(user,callback){
s.systemLog(user.mail+' : '+lang.startUpText0)
var userDetails = JSON.parse(user.details)
user.size = 0
user.limit = userDetails.size
s.sqlQuery('SELECT * FROM Videos WHERE ke=? AND status!=?',[user.ke,0],function(err,videos){
if(videos && videos[0]){
videos.forEach(function(video){
user.size += video.size
})
}
s.systemLog(user.mail+' : '+lang.startUpText1+' : '+videos.length,user.size)
callback()
})
}
var loadCloudDiskUseForUser = function(user,callback){
var userDetails = JSON.parse(user.details)
user.cloudDiskUse = {}
user.size = 0
user.limit = userDetails.size
s.cloudDisksLoaded.forEach(function(storageType){
user.cloudDiskUse[storageType] = {
usedSpace : 0,
firstCount : 0
}
if(s.cloudDiskUseStartupExtensions[storageType])s.cloudDiskUseStartupExtensions[storageType](user,userDetails)
})
s.sqlQuery('SELECT * FROM `Cloud Videos` WHERE ke=? AND status!=?',[user.ke,0],function(err,videos){
if(videos && videos[0]){
videos.forEach(function(video){
var storageType = JSON.parse(video.details).type
if(!storageType)storageType = 's3'
user.cloudDiskUse[storageType].usedSpace += (video.size /1000000)
++user.cloudDiskUse[storageType].firstCount
})
s.cloudDisksLoaded.forEach(function(storageType){
var firstCount = user.cloudDiskUse[storageType].firstCount
s.systemLog(user.mail+' : '+lang.startUpText1+' : '+firstCount,storageType,user.cloudDiskUse[storageType].usedSpace)
delete(user.cloudDiskUse[storageType].firstCount)
})
}
s.group[user.ke].cloudDiskUse = user.cloudDiskUse
callback()
})
}
var loadAdminUsers = function(callback){
//get current disk used for each isolated account (admin user) on startup
s.sqlQuery('SELECT * FROM Users WHERE details NOT LIKE ?',['%"sub"%'],function(err,users){
if(users && users[0]){
var count = users.length
var countFinished = 0
users.forEach(function(user){
loadedAccounts.push(user.ke)
var userDetails = JSON.parse(user.details)
user.size = 0
user.limit = userDetails.size
s.sqlQuery('SELECT * FROM Videos WHERE ke=? AND status!=?',[user.ke,0],function(err,videos){
if(videos && videos[0]){
videos.forEach(function(video){
user.size += video.size
})
}
s.loadGroup(user)
s.loadGroupApps(user)
++countFinished
s.systemLog(user.mail+' : '+lang.startUpText0+' : '+videos.length,user.size)
s.systemLog(user.mail+' : '+lang.startUpText1,countFinished+'/'+count)
if(countFinished === count){
callback()
}
var loadLocalDiskUse = function(callback){
var count = users.length
var countFinished = 0
users.forEach(function(user){
loadedAccounts.push(user.ke)
loadDiskUseForUser(user,function(){
s.loadGroup(user)
s.loadGroupApps(user)
++countFinished
if(countFinished === count){
callback()
}
})
})
}
var loadCloudDiskUse = function(callback){
var count = users.length
var countFinished = 0
users.forEach(function(user){
loadCloudDiskUseForUser(user,function(){
++countFinished
if(countFinished === count){
callback()
}
})
})
}
loadLocalDiskUse(function(){
loadCloudDiskUse(function(){
callback()
})
})
}else{

View File

@ -2,12 +2,10 @@ var fs = require('fs');
var events = require('events');
var spawn = require('child_process').spawn;
var exec = require('child_process').exec;
var request = require('request');
var webdav = require("webdav-fs");
module.exports = function(s,config){
s.purgeDiskForGroup = function(e,video){
s.purgeDiskForGroup = function(e){
if(s.group[e.ke].diskUsedEmitter){
s.group[e.ke].diskUsedEmitter.emit('purge',video)
s.group[e.ke].diskUsedEmitter.emit('purge')
}
}
s.setDiskUsedForGroup = function(e,bytes){
@ -16,6 +14,17 @@ module.exports = function(s,config){
s.group[e.ke].diskUsedEmitter.emit('set',bytes)
}
}
s.purgeCloudDiskForGroup = function(e,storageType){
if(s.group[e.ke].diskUsedEmitter){
s.group[e.ke].diskUsedEmitter.emit('purgeCloud',storageType)
}
}
s.setCloudDiskUsedForGroup = function(e,usage){
//`bytes` will be used as the value to add or substract
if(s.group[e.ke].diskUsedEmitter){
s.group[e.ke].diskUsedEmitter.emit('setCloud',usage)
}
}
s.sendDiskUsedAmountToClients = function(e){
//send the amount used disk space to connected users
if(s.group[e.ke]&&s.group[e.ke].init){
@ -29,7 +38,6 @@ module.exports = function(s,config){
s.sqlQuery('INSERT INTO Logs (ke,mid,info) VALUES (?,?,?)',[e.ke,e.mid,s.s(x)]);
}
s.tx({f:'log',ke:e.ke,mid:e.mid,log:x,time:s.timeObject()},'GRPLOG_'+e.ke);
// s.systemLog('s.log : ',{f:'log',ke:e.ke,mid:e.mid,log:x,time:s.timeObject()},'GRP_'+e.ke)
}
s.loadGroup = function(e){
if(!s.group[e.ke]){
@ -49,7 +57,29 @@ module.exports = function(s,config){
//emit the changes to connected users
s.sendDiskUsedAmountToClients(e)
}
s.loadGroupAppExtensions = []
s.loadGroupAppExtender = function(callback){
s.loadGroupAppExtensions.push(callback)
}
s.unloadGroupAppExtensions = []
s.unloadGroupAppExtender = function(callback){
s.unloadGroupAppExtensions.push(callback)
}
s.cloudDisksLoaded = []
s.cloudDisksLoader = function(storageType){
s.cloudDisksLoaded.push(storageType)
}
s.onAccountSaveExtensions = []
s.onAccountSave = function(callback){
s.onAccountSaveExtensions.push(callback)
}
s.beforeAccountSaveExtensions = []
s.beforeAccountSave = function(callback){
s.beforeAccountSaveExtensions.push(callback)
}
s.cloudDiskUseStartupExtensions = {}
s.loadGroupApps = function(e){
// e = user
if(!s.group[e.ke].init){
s.group[e.ke].init={};
}
@ -57,65 +87,73 @@ module.exports = function(s,config){
if(r&&r[0]){
r=r[0];
ar=JSON.parse(r.details);
//owncloud/webdav
if(!s.group[e.ke].webdav &&
ar.webdav_user&&
ar.webdav_user!==''&&
ar.webdav_pass&&
ar.webdav_pass!==''&&
ar.webdav_url&&
ar.webdav_url!==''
){
if(!ar.webdav_dir||ar.webdav_dir===''){
ar.webdav_dir='/'
}
ar.webdav_dir = s.checkCorrectPathEnding(ar.webdav_dir)
s.group[e.ke].webdav = webdav(
ar.webdav_url,
ar.webdav_user,
ar.webdav_pass
)
}
//Amazon S3
if(!s.group[e.ke].aws &&
!s.group[e.ke].aws_s3 &&
ar.aws_s3 !== '0' &&
ar.aws_accessKeyId !== ''&&
ar.aws_secretAccessKey &&
ar.aws_secretAccessKey !== ''&&
ar.aws_region &&
ar.aws_region !== ''&&
ar.aws_s3_bucket !== ''
){
if(!ar.aws_s3_dir || ar.aws_s3_dir === '/'){
ar.aws_s3_dir = ''
}
if(ar.aws_s3_dir !== ''){
ar.aws_s3_dir = s.checkCorrectPathEnding(ar.aws_s3_dir)
}
s.group[e.ke].aws = new require("aws-sdk")
s.group[e.ke].aws.config = new s.group[e.ke].aws.Config({
accessKeyId: ar.aws_accessKeyId,
secretAccessKey: ar.aws_secretAccessKey,
region: ar.aws_region
})
s.group[e.ke].aws_s3 = new s.group[e.ke].aws.S3();
}
//discordbot
if(!s.group[e.ke].discordBot &&
config.discordBot === true &&
ar.discordbot === '1' &&
ar.discordbot_token !== ''
){
s.group[e.ke].discordBot = new Discord.Client()
s.group[e.ke].discordBot.on('ready', () => {
console.log(`${r.mail} : Discord Bot Logged in as ${s.group[e.ke].discordBot.user.tag}!`)
})
s.group[e.ke].discordBot.login(ar.discordbot_token)
}
//load extenders
s.loadGroupAppExtensions.forEach(function(extender){
extender(r)
})
//disk Used Emitter
if(!s.group[e.ke].diskUsedEmitter){
s.group[e.ke].diskUsedEmitter = new events.EventEmitter()
s.group[e.ke].diskUsedEmitter.on('setCloud',function(currentChange){
var amount = currentChange.amount
var storageType = currentChange.storageType
var cloudDisk = s.group[e.ke].cloudDiskUse[storageType]
//validate current values
if(!cloudDisk.usedSpace){
cloudDisk.usedSpace = 0
}else{
cloudDisk.usedSpace = parseFloat(cloudDisk.usedSpace)
}
if(cloudDisk.usedSpace < 0 || isNaN(cloudDisk.usedSpace)){
cloudDisk.usedSpace = 0
}
//change global size value
cloudDisk.usedSpace = cloudDisk.usedSpace + amount
})
s.group[e.ke].diskUsedEmitter.on('purgeCloud',function(storageType){
if(config.cron.deleteOverMax === true){
//set queue processor
var finish=function(){
// s.sendDiskUsedAmountToClients(e)
}
var deleteVideos = function(){
//run purge command
var cloudDisk = s.group[e.ke].cloudDiskUse[storageType]
if(cloudDisk.sizeLimitCheck && cloudDisk.usedSpace > (cloudDisk.sizeLimit*config.cron.deleteOverMaxOffset)){
s.sqlQuery('SELECT * FROM `Cloud Videos` WHERE status != 0 AND ke=? AND details LIKE \'%"type":"'+storageType+'"%\' ORDER BY `time` ASC LIMIT 2',[e.ke],function(err,videos){
var videosToDelete = []
var queryValues = [e.ke]
if(!videos)return console.log(err)
videos.forEach(function(video){
video.dir = s.getVideoDirectory(video) + s.formattedTime(video.time) + '.' + video.ext
videosToDelete.push('(mid=? AND `time`=?)')
queryValues.push(video.mid)
queryValues.push(video.time)
s.setCloudDiskUsedForGroup(e,{
amount : -(video.size/1000000),
storageType : storageType
})
s.deleteVideoFromCloudExtensionsRunner(e,storageType,video)
})
if(videosToDelete.length > 0){
videosToDelete = videosToDelete.join(' OR ')
s.sqlQuery('DELETE FROM `Cloud Videos` WHERE ke =? AND ('+videosToDelete+')',queryValues,function(){
deleteVideos()
})
}else{
finish()
}
})
}else{
finish()
}
}
deleteVideos()
}else{
// s.sendDiskUsedAmountToClients(e)
}
})
//s.setDiskUsedForGroup
s.group[e.ke].diskUsedEmitter.on('set',function(currentChange){
//validate current values
if(!s.group[e.ke].usedSpace){
@ -131,30 +169,39 @@ module.exports = function(s,config){
//remove value just used from queue
s.sendDiskUsedAmountToClients(e)
})
s.group[e.ke].diskUsedEmitter.on('purge',function(currentPurge){
s.setDiskUsedForGroup(e,currentPurge.filesizeMB)
if(config.cron.deleteOverMax===true){
s.group[e.ke].diskUsedEmitter.on('purge',function(){
if(config.cron.deleteOverMax === true){
//set queue processor
var finish=function(){
s.sendDiskUsedAmountToClients(e)
}
var deleteVideos = function(){
//run purge command
if(s.group[e.ke].usedSpace>(s.group[e.ke].sizeLimit*config.cron.deleteOverMaxOffset)){
s.sqlQuery('SELECT * FROM Videos WHERE status != 0 AND details NOT LIKE \'%"archived":"1"%\' AND ke=? ORDER BY `time` ASC LIMIT 2',[e.ke],function(err,evs){
k.del=[];k.ar=[e.ke];
if(!evs)return console.log(err)
evs.forEach(function(ev){
ev.dir=s.getVideoDirectory(ev)+s.formattedTime(ev.time)+'.'+ev.ext;
k.del.push('(mid=? AND `time`=?)');
k.ar.push(ev.mid),k.ar.push(ev.time);
s.file('delete',ev.dir);
s.setDiskUsedForGroup(e,-(ev.size/1000000))
s.tx({f:'video_delete',ff:'over_max',filename:s.formattedTime(ev.time)+'.'+ev.ext,mid:ev.mid,ke:ev.ke,time:ev.time,end:s.formattedTime(new Date,'YYYY-MM-DD HH:mm:ss')},'GRP_'+e.ke);
});
if(k.del.length>0){
k.qu=k.del.join(' OR ');
s.sqlQuery('DELETE FROM Videos WHERE ke =? AND ('+k.qu+')',k.ar,function(){
if(s.group[e.ke].usedSpace > (s.group[e.ke].sizeLimit*config.cron.deleteOverMaxOffset)){
s.sqlQuery('SELECT * FROM Videos WHERE status != 0 AND details NOT LIKE \'%"archived":"1"%\' AND ke=? ORDER BY `time` ASC LIMIT 2',[e.ke],function(err,videos){
var videosToDelete = []
var queryValues = [e.ke]
if(!videos)return console.log(err)
videos.forEach(function(video){
video.dir = s.getVideoDirectory(video) + s.formattedTime(video.time) + '.' + video.ext
videosToDelete.push('(mid=? AND `time`=?)')
queryValues.push(video.mid)
queryValues.push(video.time)
s.file('delete',video.dir)
s.setDiskUsedForGroup(e,-(video.size/1000000))
s.tx({
f: 'video_delete',
ff: 'over_max',
filename: s.formattedTime(video.time)+'.'+video.ext,
mid: video.mid,
ke: video.ke,
time: video.time,
end: s.formattedTime(new Date,'YYYY-MM-DD HH:mm:ss')
},'GRP_'+e.ke)
})
if(videosToDelete.length > 0){
videosToDelete = videosToDelete.join(' OR ')
s.sqlQuery('DELETE FROM Videos WHERE ke =? AND ('+videosToDelete+')',queryValues,function(){
deleteVideos()
})
}else{

View File

@ -45,123 +45,12 @@ module.exports = function(s,config,lang){
v.details = details
})
}
s.uploadVideoToWebDav = function(e,k){
//e = video object
//k = temporary values
if(!k)k={};
//cloud saver - webdav
var wfs = s.group[e.ke].webdav
if(wfs && s.group[e.ke].init.use_webdav !== '0' && s.group[e.ke].init.webdav_save === "1"){
var webdavUploadDir = s.group[e.ke].init.webdav_dir+e.ke+'/'+e.mid+'/'
var startWebDavUpload = function(){
s.group[e.ke].mon[e.id].webdavDirExist = true
var wfsWriteStream =
fs.createReadStream(k.dir + k.filename).pipe(wfs.createWriteStream(webdavUploadDir + k.filename))
if(s.group[e.ke].init.webdav_log === '1'){
var webdavRemoteUrl = s.addUserPassToUrl(s.checkCorrectPathEnding(s.group[e.ke].init.webdav_url),s.group[e.ke].init.webdav_user,s.group[e.ke].init.webdav_pass) + s.group[e.ke].init.webdav_dir + e.ke + '/'+e.mid+'/'+k.filename
var save = [
e.mid,
e.ke,
k.startTime,
1,
s.s({
type : 'webdav'
}),
k.filesize,
k.endTime,
webdavRemoteUrl
]
s.sqlQuery('INSERT INTO `Cloud Videos` (mid,ke,time,status,details,size,end,href) VALUES (?,?,?,?,?,?,?,?)',save)
}
}
if(s.group[e.ke].mon[e.id].webdavDirExist !== true){
//check if webdav dir exist
var parentPoint = 0
var webDavParentz = webdavUploadDir.split('/')
var webDavParents = []
webDavParentz.forEach(function(v){
if(v && v !== '')webDavParents.push(v)
})
var stitchPieces = './'
var lastParentCheck = function(){
++parentPoint
if(parentPoint === webDavParents.length){
startWebDavUpload()
}
checkPathPiece(webDavParents[parentPoint])
}
var checkPathPiece = function(pathPiece){
if(pathPiece && pathPiece !== ''){
stitchPieces += pathPiece + '/'
wfs.stat(stitchPieces, function(error, stats) {
if(error){
reply = {
status : error.status,
msg : lang.WebdavErrorTextTryCreatingDir,
dir : stitchPieces,
}
s.log(e,{type:lang['Webdav Error'],msg:reply})
wfs.mkdir(stitchPieces, function(error) {
if(error){
reply = {
status : error.status,
msg : lang.WebdavErrorTextCreatingDir,
dir : stitchPieces,
}
s.log(e,{type:lang['Webdav Error'],msg:reply})
}else{
lastParentCheck()
}
})
}else{
lastParentCheck()
}
})
}else{
++parentPoint
}
}
checkPathPiece(webDavParents[0])
}else{
startWebDavUpload()
}
}
}
s.uploadVideoToAmazonS3 = function(e,k){
//e = video object
//k = temporary values
if(!k)k={};
//cloud saver - amazon s3
if(s.group[e.ke].aws_s3 && s.group[e.ke].init.use_aws_s3 !== '0' && s.group[e.ke].init.aws_s3_save === '1'){
var fileStream = fs.createReadStream(k.dir+k.filename);
fileStream.on('error', function (err) {
console.error(err)
})
s.group[e.ke].aws_s3.upload({
Bucket: s.group[e.ke].init.aws_s3_bucket,
Key: s.group[e.ke].init.aws_s3_dir+e.ke+'/'+e.mid+'/'+k.filename,
Body:fileStream,
ACL:'public-read'
},function(err,data){
if(err){
s.log(e,{type:lang['Amazon S3 Upload Error'],msg:err})
}
if(s.group[e.ke].init.aws_s3_log === '1' && data && data.Location){
var save = [
e.mid,
e.ke,
k.startTime,
1,
'{}',
k.filesize,
k.endTime,
data.Location
]
s.sqlQuery('INSERT INTO `Cloud Videos` (mid,ke,time,status,details,size,end,href) VALUES (?,?,?,?,?,?,?,?)',save)
}
})
}
//extender for "s.insertCompletedVideo"
s.insertCompletedVideoExtensions = []
s.insertCompletedVideoExtender = function(callback){
s.insertCompletedVideoExtensions.push(callback)
}
//on video completion
s.insertCompletedVideo = function(e,k){
//e = video object
//k = temporary values
@ -246,8 +135,9 @@ module.exports = function(s,config,lang){
end:k.endTime
},'GRP_'+e.ke,'video_view');
}
s.uploadVideoToWebDav(e,k)
s.uploadVideoToAmazonS3(e,k)
s.insertCompletedVideoExtensions.forEach(function(extender){
extender(e,k)
})
k.details = {}
if(e.details&&e.details.dir&&e.details.dir!==''){
k.details.dir = e.details.dir
@ -264,8 +154,10 @@ module.exports = function(s,config,lang){
k.endTime,
]
s.sqlQuery('INSERT INTO Videos (mid,ke,time,ext,status,details,size,end) VALUES (?,?,?,?,?,?,?,?)',save)
//purge over max
s.purgeDiskForGroup(e)
//send new diskUsage values
s.purgeDiskForGroup(e,k)
s.setDiskUsedForGroup(e,k.filesizeMB)
}
}
}
@ -308,10 +200,38 @@ module.exports = function(s,config,lang){
}
})
}
s.deleteVideoFromCloudExtensions = {}
s.deleteVideoFromCloudExtensionsRunner = function(e,storageType,video){
// e = user
if(!storageType){
var videoDetails = JSON.parse(r.details)
videoDetails.type = videoDetails.type || 's3'
}
if(s.deleteVideoFromCloudExtensions[storageType]){
s.deleteVideoFromCloudExtensions[storageType](e,video,function(){
s.tx({
f: 'video_delete_cloud',
mid: e.mid,
ke: e.ke,
time: e.time,
end: e.end
},'GRP_'+e.ke);
})
}
}
s.deleteVideoFromCloud = function(e){
//e = video object
s.sqlQuery('DELETE FROM `Cloud Videos` WHERE `mid`=? AND `ke`=? AND `time`=?',[e.id,e.ke,new Date(e.time)],function(){
s.tx({f:'video_delete_cloud',mid:e.mid,ke:e.ke,time:e.time,end:e.end},'GRP_'+e.ke);
var videoSelector = [e.id,e.ke,new Date(e.time)]
s.sqlQuery('SELECT * FROM `Cloud Videos` WHERE `mid`=? AND `ke`=? AND `time`=?',videoSelector,function(err,r){
if(r&&r[0]){
r = r[0]
s.sqlQuery('DELETE FROM `Cloud Videos` WHERE `mid`=? AND `ke`=? AND `time`=?',videoSelector,function(){
s.deleteVideoFromCloudExtensionsRunner(e,r)
})
}else{
// console.log('Delete Failed',e)
// console.error(err)
}
})
}
}

View File

@ -84,9 +84,9 @@ module.exports = function(s,config,lang,app){
delete(s.api[req.params.auth]);
delete(s.group[req.params.ke].users[req.params.auth]);
s.sqlQuery("UPDATE Users SET auth=? WHERE auth=? AND ke=? AND uid=?",['',req.params.auth,req.params.ke,req.params.id])
res.end(s.s({ok:true,msg:'You have been logged out, session key is now inactive.'}))
res.end(s.prettyPrint({ok:true,msg:'You have been logged out, session key is now inactive.'}))
}else{
res.end(s.s({ok:false,msg:'This group key does not exist or this user is not logged in.'}))
res.end(s.prettyPrint({ok:false,msg:'This group key does not exist or this user is not logged in.'}))
}
});
//main page
@ -132,7 +132,7 @@ module.exports = function(s,config,lang,app){
}else{
req.ret.msg=user.lang.updateKeyText2;
}
res.end(s.s(req.ret));
res.end(s.prettyPrint(req.ret));
}
s.auth(req.params,req.fn,res,req);
});
@ -144,7 +144,7 @@ module.exports = function(s,config,lang,app){
s.auth(req.params,function(user){
req.ret.ok=true
req.ret.user=user
res.end(s.s(req.ret));
res.end(s.prettyPrint(req.ret));
},res,req);
})
//register function
@ -170,7 +170,7 @@ module.exports = function(s,config,lang,app){
s.sqlQuery('INSERT INTO Users (ke,uid,mail,pass,details) VALUES (?,?,?,?,?)',[req.params.ke,req.gid,req.body.mail,s.createHash(req.body.pass),req.body.details])
s.tx({f:'add_sub_account',details:req.body.details,ke:req.params.ke,uid:req.gid,mail:req.body.mail},'ADM_'+req.params.ke);
}
res.end(s.s(req.resp));
res.end(s.prettyPrint(req.resp));
})
}else{
req.resp.msg=user.lang['Passwords Don\'t Match'];
@ -182,7 +182,7 @@ module.exports = function(s,config,lang,app){
req.resp.msg=user.lang['Not an Administrator Account'];
}
if(req.resp.msg){
res.end(s.s(req.resp));
res.end(s.prettyPrint(req.resp));
}
})
},res,req);
@ -202,7 +202,7 @@ module.exports = function(s,config,lang,app){
// brute check
if(s.failedLoginAttempts[req.body.mail] && s.failedLoginAttempts[req.body.mail].failCount >= 5){
if(req.query.json=='true'){
res.end(s.s({ok:false}))
res.end(s.prettyPrint({ok:false}))
}else{
res.render(config.renderPaths.index,{
failedLogin:true,
@ -230,7 +230,7 @@ module.exports = function(s,config,lang,app){
delete(data.config)
data.ok=true;
res.setHeader('Content-Type', 'application/json');
res.end(s.s(data))
res.end(s.prettyPrint(data))
}else{
data.originalURL = s.getOriginalUrl(req)
data.screen=req.params.screen
@ -262,7 +262,7 @@ module.exports = function(s,config,lang,app){
// check if JSON
if(req.query.json=='true'){
res.setHeader('Content-Type', 'application/json');
res.end(s.s({ok:false}))
res.end(s.prettyPrint({ok:false}))
}else{
res.render(config.renderPaths.index,{
failedLogin:true,
@ -556,7 +556,7 @@ module.exports = function(s,config,lang,app){
}
if(!req.details.acceptedMachines[req.body.machineID]){
req.details.acceptedMachines[req.body.machineID]={}
s.sqlQuery("UPDATE Users SET details=? WHERE ke=? AND uid=?",[s.s(req.details),req.body.ke,req.body.id])
s.sqlQuery("UPDATE Users SET details=? WHERE ke=? AND uid=?",[s.prettyPrint(req.details),req.body.ke,req.body.id])
}
}
req.body.function = s.factorAuth[req.body.ke][req.body.id].function
@ -582,7 +582,7 @@ module.exports = function(s,config,lang,app){
clearTimeout(s.failedLoginAttempts[user.mail].timeout)
delete(s.failedLoginAttempts[user.mail])
}
res.end(s.s({ok:true}))
res.end(s.prettyPrint({ok:true}))
})
})
// Get HLS stream (m3u8)
@ -661,7 +661,7 @@ module.exports = function(s,config,lang,app){
})
}else{
res.setHeader('Content-Type', 'application/json');
res.end(s.s({ok:false,msg:'FLV not started or not ready'}))
res.end(s.prettyPrint({ok:false,msg:'FLV not started or not ready'}))
}
},res,req)
},res,req)
@ -904,7 +904,7 @@ module.exports = function(s,config,lang,app){
res.header("Access-Control-Allow-Origin",req.headers.origin);
req.fn=function(user){
if(user.permissions.get_monitors==="0"){
res.end(s.s([]))
res.end(s.prettyPrint([]))
return
}
if(!req.params.ke){
@ -1005,7 +1005,7 @@ module.exports = function(s,config,lang,app){
res.end(m3u8)
}else{
if(tvChannelMonitors.length===1){tvChannelMonitors=tvChannelMonitors[0];}
res.end(s.s(tvChannelMonitors));
res.end(s.prettyPrint(tvChannelMonitors));
}
})
}
@ -1018,7 +1018,7 @@ module.exports = function(s,config,lang,app){
res.header("Access-Control-Allow-Origin",req.headers.origin);
req.fn=function(user){
if(user.permissions.get_monitors==="0"){
res.end(s.s([]))
res.end(s.prettyPrint([]))
return
}
req.sql='SELECT * FROM Monitors WHERE ke=?';req.ar=[req.params.ke];
@ -1092,7 +1092,7 @@ module.exports = function(s,config,lang,app){
}
})
if(r.length===1){r=r[0];}
res.end(s.s(r));
res.end(s.prettyPrint(r));
})
}
s.auth(req.params,req.fn,res,req);
@ -1112,7 +1112,7 @@ module.exports = function(s,config,lang,app){
user.permissions.watch_videos==="0" ||
hasRestrictions && (!user.details.video_view || user.details.video_view.indexOf(req.params.id)===-1)
){
res.end(s.s([]))
res.end(s.prettyPrint([]))
return
}
var origURL = req.originalUrl.split('/')
@ -1193,7 +1193,7 @@ module.exports = function(s,config,lang,app){
}
s.sqlQuery(req.sql,req.ar,function(err,r){
if(!r){
res.end(s.s({total:0,limit:req.query.limit,skip:0,videos:[]}));
res.end(s.prettyPrint({total:0,limit:req.query.limit,skip:0,videos:[]}));
return
}
s.sqlQuery(req.count_sql,req.count_ar,function(err,count){
@ -1209,7 +1209,7 @@ module.exports = function(s,config,lang,app){
req.skip=0
req.query.limit=parseInt(req.query.limit)
}
res.end(s.s({isUTC:config.useUTC,total:count[0]['COUNT(*)'],limit:req.query.limit,skip:req.skip,videos:r}));
res.end(s.prettyPrint({isUTC:config.useUTC,total:count[0]['COUNT(*)'],limit:req.query.limit,skip:req.skip,videos:r}));
})
})
},res,req);
@ -1221,7 +1221,7 @@ module.exports = function(s,config,lang,app){
res.header("Access-Control-Allow-Origin",req.headers.origin);
s.auth(req.params,function(user){
if(user.permissions.watch_videos==="0"||user.details.sub&&user.details.allmonitors!=='1'&&user.details.video_view.indexOf(req.params.id)===-1){
res.end(s.s([]))
res.end(s.prettyPrint([]))
return
}
req.sql='SELECT * FROM Events WHERE ke=?';req.ar=[req.params.ke];
@ -1259,14 +1259,14 @@ module.exports = function(s,config,lang,app){
s.sqlQuery(req.sql,req.ar,function(err,r){
if(err){
err.sql=req.sql;
res.end(s.s(err));
res.end(s.prettyPrint(err));
return
}
if(!r){r=[]}
r.forEach(function(v,n){
r[n].details=JSON.parse(v.details);
})
res.end(s.s(r));
res.end(s.prettyPrint(r));
})
},res,req);
});
@ -1277,7 +1277,7 @@ module.exports = function(s,config,lang,app){
res.header("Access-Control-Allow-Origin",req.headers.origin);
s.auth(req.params,function(user){
if(user.permissions.get_logs==="0" || user.details.sub && user.details.view_logs !== '1'){
res.end(s.s([]))
res.end(s.prettyPrint([]))
return
}
req.sql='SELECT * FROM Logs WHERE ke=?';req.ar=[req.params.ke];
@ -1322,14 +1322,14 @@ module.exports = function(s,config,lang,app){
s.sqlQuery(req.sql,req.ar,function(err,r){
if(err){
err.sql=req.sql;
res.end(s.s(err));
res.end(s.prettyPrint(err));
return
}
if(!r){r=[]}
r.forEach(function(v,n){
r[n].info=JSON.parse(v.info)
})
res.end(s.s(r));
res.end(s.prettyPrint(r));
})
},res,req);
});
@ -1340,7 +1340,7 @@ module.exports = function(s,config,lang,app){
res.header("Access-Control-Allow-Origin",req.headers.origin);
req.fn=function(user){
if(user.permissions.get_monitors==="0"){
res.end(s.s([]))
res.end(s.prettyPrint([]))
return
}
req.sql='SELECT * FROM Monitors WHERE ke=?';req.ar=[req.params.ke];
@ -1363,7 +1363,7 @@ module.exports = function(s,config,lang,app){
}else{
req.ar=[];
}
res.end(s.s(req.ar));
res.end(s.prettyPrint(req.ar));
})
}
s.auth(req.params,req.fn,res,req);
@ -1378,7 +1378,7 @@ module.exports = function(s,config,lang,app){
if(req.params.f !== 'delete'){
if(!req.body.data&&!req.query.data){
req.ret.msg='No Monitor Data found.'
res.end(s.s(req.ret))
res.end(s.prettyPrint(req.ret))
return
}
try{
@ -1390,7 +1390,7 @@ module.exports = function(s,config,lang,app){
}catch(er){
if(!req.monitor){
req.ret.msg=user.lang.monitorEditText1;
res.end(s.s(req.ret))
res.end(s.prettyPrint(req.ret))
}
return
}
@ -1406,7 +1406,7 @@ module.exports = function(s,config,lang,app){
}catch(er){
if(!req.monitor.details||!req.monitor.details.stream_type){
req.ret.msg=user.lang.monitorEditText2;
res.end(s.s(req.ret))
res.end(s.prettyPrint(req.ret))
return
}else{
req.monitor.details=JSON.stringify(req.monitor.details)
@ -1463,15 +1463,15 @@ module.exports = function(s,config,lang,app){
s.tx(req.tx,'STR_'+req.monitor.ke);
};
s.tx(req.tx,'GRP_'+req.monitor.ke);
res.end(s.s(req.ret))
res.end(s.prettyPrint(req.ret))
})
}else{
req.ret.msg=user.lang.monitorEditText1;
res.end(s.s(req.ret))
res.end(s.prettyPrint(req.ret))
}
}else{
req.ret.msg=user.lang['Not Permitted'];
res.end(s.s(req.ret))
res.end(s.prettyPrint(req.ret))
}
}else{
if(!user.details.sub || user.details.allmonitors === '1' || user.details.monitor_edit.indexOf(req.params.id) > -1 || hasRestrictions && user.details.monitor_create === '1'){
@ -1506,10 +1506,10 @@ module.exports = function(s,config,lang,app){
}
req.ret.ok=true;
req.ret.msg='Monitor Deleted by user : '+user.uid
res.end(s.s(req.ret))
res.end(s.prettyPrint(req.ret))
}else{
req.ret.msg=user.lang['Not Permitted'];
res.end(s.s(req.ret))
res.end(s.prettyPrint(req.ret))
}
}
})
@ -1523,10 +1523,10 @@ module.exports = function(s,config,lang,app){
res.end(user.lang['Not Permitted'])
return
}
if(req.params.f===''){req.ret.msg=user.lang.monitorGetText1;res.end(s.s(req.ret));return}
if(req.params.f===''){req.ret.msg=user.lang.monitorGetText1;res.end(s.prettyPrint(req.ret));return}
if(req.params.f!=='stop'&&req.params.f!=='start'&&req.params.f!=='record'){
req.ret.msg='Mode not recognized.';
res.end(s.s(req.ret));
res.end(s.prettyPrint(req.ret));
return;
}
s.sqlQuery('SELECT * FROM Monitors WHERE ke=? AND mid=?',[req.params.ke,req.params.id],function(err,r){
@ -1603,7 +1603,7 @@ module.exports = function(s,config,lang,app){
}else{
req.ret.msg=user.lang['Monitor or Key does not exist.'];
}
res.end(s.s(req.ret));
res.end(s.prettyPrint(req.ret));
})
},res,req);
})
@ -1634,7 +1634,7 @@ module.exports = function(s,config,lang,app){
v.href='/'+req.params.auth+'/fileBin/'+req.params.ke+'/'+req.params.id+'/'+v.details.year+'/'+v.details.month+'/'+v.details.day+'/'+v.name;
})
}
res.end(s.s(r));
res.end(s.prettyPrint(r));
})
}
s.auth(req.params,req.fn,res,req);
@ -1673,7 +1673,7 @@ module.exports = function(s,config,lang,app){
res.header("Access-Control-Allow-Origin",req.headers.origin);
var failed = function(resp){
res.setHeader('Content-Type', 'application/json');
res.end(s.s(resp))
res.end(s.prettyPrint(resp))
}
if(req.query.videos && req.query.videos !== ''){
s.auth(req.params,function(user){
@ -1857,7 +1857,7 @@ module.exports = function(s,config,lang,app){
res.setHeader('Content-Type', 'application/json');
s.auth(req.params,function(user){
s.log(req.params,{type:'Test',msg:'Hook Test'})
res.end(s.s({ok:true}))
res.end(s.prettyPrint({ok:true}))
},res,req);
})
//control trigger
@ -1866,7 +1866,7 @@ module.exports = function(s,config,lang,app){
res.header("Access-Control-Allow-Origin",req.headers.origin);
s.auth(req.params,function(user){
s.camera('control',req.params,function(resp){
res.end(s.s(resp))
res.end(s.prettyPrint(resp))
});
},res,req);
})
@ -1942,7 +1942,7 @@ module.exports = function(s,config,lang,app){
}else{
req.ret.msg=user.lang['No such file'];
}
res.end(s.s(req.ret));
res.end(s.prettyPrint(req.ret));
})
},res,req);
})
@ -2058,12 +2058,12 @@ module.exports = function(s,config,lang,app){
default:
if(!req.query.url){
req.ret.error = 'Missing URL'
res.end(s.s(req.ret));
res.end(s.prettyPrint(req.ret));
return
}
if(user.ffprobe){
req.ret.error = 'Account is already probing'
res.end(s.s(req.ret));
res.end(s.prettyPrint(req.ret));
return
}
user.ffprobe=1;
@ -2084,7 +2084,7 @@ module.exports = function(s,config,lang,app){
req.ret.result = stdout+stderr
}
req.ret.probe = req.probeCommand
res.end(s.s(req.ret));
res.end(s.prettyPrint(req.ret));
})
break;
}
@ -2100,7 +2100,7 @@ module.exports = function(s,config,lang,app){
response.ok = false
response.msg = msg
response.error = error
res.end(s.s(response))
res.end(s.prettyPrint(response))
}
var actionCallback = function(onvifActionResponse){
response.ok = true
@ -2110,7 +2110,7 @@ module.exports = function(s,config,lang,app){
response.responseFromDevice = onvifActionResponse
}
if(onvifActionResponse.soap)response.soap = onvifActionResponse.soap
res.end(s.s(response))
res.end(s.prettyPrint(response))
}
var isEmpty = function(obj) {
for(var key in obj) {
@ -2128,10 +2128,10 @@ module.exports = function(s,config,lang,app){
}else if(command){
response.ok = true
response.repsonseFromDevice = command
res.end(s.s(response))
res.end(s.prettyPrint(response))
}else{
response.error = 'Big Errors, Please report it to Shinobi Development'
res.end(s.s(response))
res.end(s.prettyPrint(response))
}
}
var action

View File

@ -207,6 +207,19 @@
</select></div>
</label>
</div>
<div class="form-group">
<label><div><span><%-lang['Use Max Storage Amount']%></span></div>
<div><select class="form-control" detail="use_webdav_size_limit" selector="h_webdavzl">
<option value="0" selected><%-lang.No%></option>
<option value="1"><%-lang.Yes%></option>
</select></div>
</label>
</div>
<div class="form-group h_webdavzl_input h_webdavzl_1">
<label><div><span><%-lang['Max Storage Amount']%></span></div>
<div><input class="form-control" placeholder="10000" detail="webdav_size_limit"></div>
</label>
</div>
<div class="form-group">
<label><div><span><%-lang['Save Directory']%></span></div>
<div><input class="form-control" placeholder="/" detail="webdav_dir"></div>
@ -274,6 +287,19 @@
</select></div>
</label>
</div>
<div class="form-group">
<label><div><span><%-lang['Use Max Storage Amount']%></span></div>
<div><select class="form-control" detail="use_aws_s3_size_limit" selector="h_s3zl">
<option value="0" selected><%-lang.No%></option>
<option value="1"><%-lang.Yes%></option>
</select></div>
</label>
</div>
<div class="form-group h_s3zl_input h_s3zl_1">
<label><div><span><%-lang['Max Storage Amount']%></span></div>
<div><input class="form-control" placeholder="10000" detail="aws_s3_size_limit"></div>
</label>
</div>
<div class="form-group">
<label><div><span><%-lang['Save Directory']%></span></div>
<div><input class="form-control" placeholder="" detail="aws_s3_dir"></div>
@ -281,6 +307,62 @@
</div>
</div>
<% } %>
<% if(details.use_bb_b2!=='0'){ %>
<div class="form-group-group forestgreen">
<h4><%-lang['Backblaze B2']%></h4>
<div class="form-group">
<label><div><span><%-lang.Bucket%></span></div>
<div><input class="form-control" detail="bb_b2_bucket" placeholder="Example : slippery-seal"></div>
</label>
</div>
<div class="row">
<div class="form-group col-md-12">
<label><div><span><%-lang.accountId%></span></div>
<div><input class="form-control" detail="bb_b2_accountId"></div>
</label>
</div>
<div class="form-group col-md-12">
<label><div><span><%-lang.applicationKey%></span></div>
<div><input class="form-control" type="password" detail="bb_b2_applicationKey"></div>
</label>
</div>
</div>
<div class="form-group">
<label><div><span><%-lang.Autosave%></span></div>
<div><select class="form-control" detail="bb_b2_save">
<option value="0" selected><%-lang.No%></option>
<option value="1"><%-lang.Yes%></option>
</select></div>
</label>
</div>
<div class="form-group">
<label><div><span><%-lang['Save Links to Database']%></span></div>
<div><select class="form-control" detail="bb_b2_log">
<option value="0"><%-lang.No%></option>
<option value="1" selected><%-lang.Yes%></option>
</select></div>
</label>
</div>
<div class="form-group">
<label><div><span><%-lang['Use Max Storage Amount']%></span></div>
<div><select class="form-control" detail="use_bb_b2_size_limit" selector="h_b2zl">
<option value="0" selected><%-lang.No%></option>
<option value="1"><%-lang.Yes%></option>
</select></div>
</label>
</div>
<div class="form-group h_b2zl_input h_b2zl_1">
<label><div><span><%-lang['Max Storage Amount']%></span></div>
<div><input class="form-control" placeholder="10000" detail="bb_b2_size_limit"></div>
</label>
</div>
<div class="form-group">
<label><div><span><%-lang['Save Directory']%></span></div>
<div><input class="form-control" placeholder="" detail="bb_b2_dir"></div>
</label>
</div>
</div>
<% } %>
<% if(details.use_discordbot!=='0'){ %>
<div class="form-group-group forestgreen">
<h4><%-lang['Discord Bot']%></h4>