From ce7b86d3a17cab75360244e2ec3d2a326e242bc4 Mon Sep 17 00:00:00 2001 From: Moe Date: Wed, 8 Jul 2020 21:34:06 -0700 Subject: [PATCH 001/175] sqlQuery Conversion : create knexQuery, can only select for now --- libs/sql.js | 37 +++++++++++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) diff --git a/libs/sql.js b/libs/sql.js index 8ac3bd2b..bc3df06a 100644 --- a/libs/sql.js +++ b/libs/sql.js @@ -61,6 +61,43 @@ module.exports = function(s,config){ .raw(data.query,data.values) .asCallback(callback) }, 4); + const knexQuery = (options) => { + // options = { + // action: "", + // columns: "", + // tableName: "" + // } + var response + switch(options.action){ + case'select': + response = s.databaseEngine.select(...options.columns) + break; + } + response.from(options.tableName) + if(options.where){ + var didOne = false; + options.where.forEach((where) => { + var whereIsArray = where instanceof Array; + if(!didOne){ + didOne = true + whereIsArray ? response.where(...where) : response.where(where) + }else if(where.length === 4){ + switch(where[0]){ + case'and': + whereIsArray ? response.andWhere(...where) : response.andWhere(where) + break; + case'or': + whereIsArray ? response.orWhere(...where) : response.orWhere(where) + break; + } + }else{ + whereIsArray ? response.andWhere(...where) : response.andWhere(where) + } + }) + } + return response + } + s.knexQuery = knexQuery s.sqlQuery = function(query,values,onMoveOn,hideLog){ if(!values){values=[]} if(typeof values === 'function'){ From b02311386bd5c6404c0369dde125c81b6154e1ef Mon Sep 17 00:00:00 2001 From: Moe Date: Wed, 8 Jul 2020 21:34:12 -0700 Subject: [PATCH 002/175] sqlQuery Conversion : startup.js --- libs/startup.js | 62 +++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 55 insertions(+), 7 deletions(-) diff --git a/libs/startup.js b/libs/startup.js index 2ee97596..24f6e357 100644 --- a/libs/startup.js +++ b/libs/startup.js @@ -43,7 +43,11 @@ module.exports = function(s,config,lang,io){ }) s.systemLog(lang.startUpText4) //preliminary monitor start - s.sqlQuery('SELECT * FROM Monitors', function(err,monitors) { + s.knexQuery({ + action: "select", + columns: "*", + tableName: "Monitors", + }).asCallback(function(err,monitors) { foundMonitors = monitors if(err){s.systemLog(err)} if(monitors && monitors[0]){ @@ -115,9 +119,31 @@ module.exports = function(s,config,lang,io){ s.group[user.ke].sizeLimit = parseFloat(userDetails.size) || 10000 s.group[user.ke].sizeLimitVideoPercent = parseFloat(userDetails.size_video_percent) || 90 s.group[user.ke].sizeLimitTimelapseFramesPercent = parseFloat(userDetails.size_timelapse_percent) || 10 - s.sqlQuery('SELECT * FROM Videos WHERE ke=? AND status!=?',[user.ke,0],function(err,videos){ - s.sqlQuery('SELECT * FROM `Timelapse Frames` WHERE ke=?',[user.ke],function(err,timelapseFrames){ - s.sqlQuery('SELECT * FROM `Files` WHERE ke=?',[user.ke],function(err,files){ + s.knexQuery({ + action: "select", + columns: "*", + tableName: "Videos", + where: [ + ['ke','=',user.ke], + ['status','!=',0], + ] + }).asCallback(function(err,videos) { + s.knexQuery({ + action: "select", + columns: "*", + tableName: "Timelapse Frames", + where: [ + ['ke','=',user.ke], + ] + }).asCallback(function(err,timelapseFrames) { + s.knexQuery({ + action: "select", + columns: "*", + tableName: "Files", + where: [ + ['ke','=',user.ke], + ] + }).asCallback(function(err,files) { var usedSpaceVideos = 0 var usedSpaceTimelapseFrames = 0 var usedSpaceFilebin = 0 @@ -180,7 +206,15 @@ module.exports = function(s,config,lang,io){ if(s.cloudDiskUseStartupExtensions[storageType])s.cloudDiskUseStartupExtensions[storageType](user,userDetails) }) var loadCloudVideos = function(callback){ - s.sqlQuery('SELECT * FROM `Cloud Videos` WHERE ke=? AND status!=?',[user.ke,0],function(err,videos){ + s.knexQuery({ + action: "select", + columns: "*", + tableName: "Cloud Videos", + where: [ + ['ke','=',user.ke], + ['status','!=',0], + ] + }).asCallback(function(err,videos) { if(videos && videos[0]){ videos.forEach(function(video){ var storageType = JSON.parse(video.details).type @@ -200,7 +234,14 @@ module.exports = function(s,config,lang,io){ }) } var loadCloudTimelapseFrames = function(callback){ - s.sqlQuery('SELECT * FROM `Cloud Timelapse Frames` WHERE ke=?',[user.ke],function(err,frames){ + s.knexQuery({ + action: "select", + columns: "*", + tableName: "Cloud Timelapse Frames", + where: [ + ['ke','=',user.ke], + ] + }).asCallback(function(err,frames) { if(frames && frames[0]){ frames.forEach(function(frame){ var storageType = JSON.parse(frame.details).type @@ -284,7 +325,14 @@ module.exports = function(s,config,lang,io){ } 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){ + s.knexQuery({ + action: "select", + columns: "*", + tableName: "Users", + where: [ + ['details','NOT LIKE','%"sub"%'] + ] + }).asCallback(function(err,users) { if(users && users[0]){ users.forEach(function(user){ checkedAdminUsers[user.ke] = user From b7db2ecfe9dc0f6fb8e44805ab36cd1b1caca8b6 Mon Sep 17 00:00:00 2001 From: Moe Date: Wed, 8 Jul 2020 22:38:32 -0700 Subject: [PATCH 003/175] sqlQuery Conversion : add update, insert, delete to s.knexQuery + change option tableName to table --- libs/sql.js | 27 +++++++++++++++++++++++---- libs/startup.js | 14 +++++++------- 2 files changed, 30 insertions(+), 11 deletions(-) diff --git a/libs/sql.js b/libs/sql.js index bc3df06a..892f6c7d 100644 --- a/libs/sql.js +++ b/libs/sql.js @@ -62,18 +62,30 @@ module.exports = function(s,config){ .asCallback(callback) }, 4); const knexQuery = (options) => { + if(config.debugLog === true){ + s.debugLog('s.knexQuery QUERY',options) + } // options = { // action: "", // columns: "", - // tableName: "" + // table: "" // } var response switch(options.action){ case'select': - response = s.databaseEngine.select(...options.columns) + if(!options.columns)options.columns = '*' + response = s.databaseEngine.select(...options.columns).from(options.table) + break; + case'update': + response = s.databaseEngine(options.table).update(options.update) + break; + case'delete': + response = s.databaseEngine(options.table).del() + break; + case'insert': + response = s.databaseEngine(options.table).insert(options.insert) break; } - response.from(options.tableName) if(options.where){ var didOne = false; options.where.forEach((where) => { @@ -82,7 +94,9 @@ module.exports = function(s,config){ didOne = true whereIsArray ? response.where(...where) : response.where(where) }else if(where.length === 4){ - switch(where[0]){ + const separator = where[0] + '' + where.shift() + switch(separator){ case'and': whereIsArray ? response.andWhere(...where) : response.andWhere(where) break; @@ -95,6 +109,11 @@ module.exports = function(s,config){ } }) } + if(options.update || options.insert){ + response.asCallback(function(err,r) { + if(err)console.log(err) + }) + } return response } s.knexQuery = knexQuery diff --git a/libs/startup.js b/libs/startup.js index 24f6e357..cee5c69b 100644 --- a/libs/startup.js +++ b/libs/startup.js @@ -46,7 +46,7 @@ module.exports = function(s,config,lang,io){ s.knexQuery({ action: "select", columns: "*", - tableName: "Monitors", + table: "Monitors", }).asCallback(function(err,monitors) { foundMonitors = monitors if(err){s.systemLog(err)} @@ -122,7 +122,7 @@ module.exports = function(s,config,lang,io){ s.knexQuery({ action: "select", columns: "*", - tableName: "Videos", + table: "Videos", where: [ ['ke','=',user.ke], ['status','!=',0], @@ -131,7 +131,7 @@ module.exports = function(s,config,lang,io){ s.knexQuery({ action: "select", columns: "*", - tableName: "Timelapse Frames", + table: "Timelapse Frames", where: [ ['ke','=',user.ke], ] @@ -139,7 +139,7 @@ module.exports = function(s,config,lang,io){ s.knexQuery({ action: "select", columns: "*", - tableName: "Files", + table: "Files", where: [ ['ke','=',user.ke], ] @@ -209,7 +209,7 @@ module.exports = function(s,config,lang,io){ s.knexQuery({ action: "select", columns: "*", - tableName: "Cloud Videos", + table: "Cloud Videos", where: [ ['ke','=',user.ke], ['status','!=',0], @@ -237,7 +237,7 @@ module.exports = function(s,config,lang,io){ s.knexQuery({ action: "select", columns: "*", - tableName: "Cloud Timelapse Frames", + table: "Cloud Timelapse Frames", where: [ ['ke','=',user.ke], ] @@ -328,7 +328,7 @@ module.exports = function(s,config,lang,io){ s.knexQuery({ action: "select", columns: "*", - tableName: "Users", + table: "Users", where: [ ['details','NOT LIKE','%"sub"%'] ] From e1cc2d3fece2a4d836ab32dc7b04c4068eafe4af Mon Sep 17 00:00:00 2001 From: Moe Date: Wed, 8 Jul 2020 22:51:45 -0700 Subject: [PATCH 004/175] sqlQuery Conversion : rename response to dbQuery --- libs/sql.js | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/libs/sql.js b/libs/sql.js index 892f6c7d..df28791b 100644 --- a/libs/sql.js +++ b/libs/sql.js @@ -70,20 +70,20 @@ module.exports = function(s,config){ // columns: "", // table: "" // } - var response + var dbQuery switch(options.action){ case'select': if(!options.columns)options.columns = '*' - response = s.databaseEngine.select(...options.columns).from(options.table) + dbQuery = s.databaseEngine.select(...options.columns).from(options.table) break; case'update': - response = s.databaseEngine(options.table).update(options.update) + dbQuery = s.databaseEngine(options.table).update(options.update) break; case'delete': - response = s.databaseEngine(options.table).del() + dbQuery = s.databaseEngine(options.table).del() break; case'insert': - response = s.databaseEngine(options.table).insert(options.insert) + dbQuery = s.databaseEngine(options.table).insert(options.insert) break; } if(options.where){ @@ -92,29 +92,29 @@ module.exports = function(s,config){ var whereIsArray = where instanceof Array; if(!didOne){ didOne = true - whereIsArray ? response.where(...where) : response.where(where) + whereIsArray ? dbQuery.where(...where) : dbQuery.where(where) }else if(where.length === 4){ const separator = where[0] + '' where.shift() switch(separator){ case'and': - whereIsArray ? response.andWhere(...where) : response.andWhere(where) + whereIsArray ? dbQuery.andWhere(...where) : dbQuery.andWhere(where) break; case'or': - whereIsArray ? response.orWhere(...where) : response.orWhere(where) + whereIsArray ? dbQuery.orWhere(...where) : dbQuery.orWhere(where) break; } }else{ - whereIsArray ? response.andWhere(...where) : response.andWhere(where) + whereIsArray ? dbQuery.andWhere(...where) : dbQuery.andWhere(where) } }) } if(options.update || options.insert){ - response.asCallback(function(err,r) { + dbQuery.asCallback(function(err,r) { if(err)console.log(err) }) } - return response + return dbQuery } s.knexQuery = knexQuery s.sqlQuery = function(query,values,onMoveOn,hideLog){ From b99e258f8f32468158c7e5c395d2052c3293ddd5 Mon Sep 17 00:00:00 2001 From: Moe Date: Wed, 8 Jul 2020 22:52:49 -0700 Subject: [PATCH 005/175] sqlQuery Conversion : monitor.js --- libs/monitor.js | 95 ++++++++++++++++++++++++++++++++----------------- 1 file changed, 62 insertions(+), 33 deletions(-) diff --git a/libs/monitor.js b/libs/monitor.js index d2c088af..f11daaf1 100644 --- a/libs/monitor.js +++ b/libs/monitor.js @@ -539,6 +539,9 @@ module.exports = function(s,config,lang){ s.tx({f:'monitor_snapshot',snapshot:e.mon.name,snapshot_format:'plc',mid:e.mid,ke:e.ke},'GRP_'+e.ke) } } + s.getStreamsDirectory = (monitor) => { + return s.dir.streams + monitor.ke + '/' + monitor.mid + '/' + } const createRecordingDirectory = function(e,callback){ var directory if(e.details && e.details.dir && e.details.dir !== '' && config.childNodes.mode !== 'child'){ @@ -764,18 +767,22 @@ module.exports = function(s,config,lang){ const count = Object.keys(tagInfo.count) const times = tagInfo.times const realTag = tagInfo.tag - s.sqlQuery('INSERT INTO `Events Counts` (ke,mid,details,time,end,count,tag) VALUES (?,?,?,?,?,?,?)',[ - groupKey, - monitorId, - JSON.stringify({ - times: times, - count: count, - }), - startTime, - endTime, - count.length, - realTag - ]) + s.knexQuery({ + action: "insert", + table: "Events Counts", + insert: { + ke: groupKey, + mid: monitorId, + details: JSON.stringify({ + times: times, + count: count, + }), + time: startTime, + end: endTime, + count: count.length, + tag: realTag + } + }) }) },60000) //every minute } @@ -1395,10 +1402,17 @@ module.exports = function(s,config,lang){ } form.mid = form.mid.replace(/[^\w\s]/gi,'').replace(/ /g,'') form = s.cleanMonitorObjectForDatabase(form) - s.sqlQuery('SELECT * FROM Monitors WHERE ke=? AND mid=?',[form.ke,form.mid],function(er,r){ + s.knexQuery({ + action: "select", + columns: "*", + table: "Monitors", + where: [ + ['ke','=',form.ke], + ['mid','=',form.mid], + ] + }).asCallback(function(err,r) { var affectMonitor = false - var monitorQuery = [] - var monitorQueryValues = [] + var monitorQuery = {} var txData = { f: 'monitor_edit', mid: form.mid, @@ -1416,19 +1430,23 @@ module.exports = function(s,config,lang){ form[v] !== false && form[v] !== `false` ){ - monitorQuery.push(v+'=?') if(form[v] instanceof Object){ form[v] = s.s(form[v]) } - monitorQueryValues.push(form[v]) + monitorQuery[v] = form[v] } }) - monitorQuery = monitorQuery.join(',') - monitorQueryValues.push(form.ke) - monitorQueryValues.push(form.mid) s.userLog(form,{type:'Monitor Updated',msg:'by user : '+user.uid}) endData.msg = user.lang['Monitor Updated by user']+' : '+user.uid - s.sqlQuery('UPDATE Monitors SET '+monitorQuery+' WHERE ke=? AND mid=?',monitorQueryValues) + s.knexQuery({ + action: "update", + table: "Monitors", + update: monitorQuery, + where: [ + ['ke','=',form.ke], + ['mid','=',form.mid], + ] + }) affectMonitor = true }else if( !s.group[form.ke].init.max_camera || @@ -1436,22 +1454,21 @@ module.exports = function(s,config,lang){ Object.keys(s.group[form.ke].activeMonitors).length <= parseInt(s.group[form.ke].init.max_camera) ){ txData.new = true - monitorQueryInsertValues = [] Object.keys(form).forEach(function(v){ if(form[v] && form[v] !== ''){ - monitorQuery.push(v) - monitorQueryInsertValues.push('?') if(form[v] instanceof Object){ form[v] = s.s(form[v]) } - monitorQueryValues.push(form[v]) + monitorQuery[v] = form[v] } }) - monitorQuery = monitorQuery.join(',') - monitorQueryInsertValues = monitorQueryInsertValues.join(',') s.userLog(form,{type:'Monitor Added',msg:'by user : '+user.uid}) endData.msg = user.lang['Monitor Added by user']+' : '+user.uid - s.sqlQuery('INSERT INTO Monitors ('+monitorQuery+') VALUES ('+monitorQueryInsertValues+')',monitorQueryValues) + s.knexQuery({ + action: "insert", + table: "Monitors", + insert: monitorQuery + }) affectMonitor = true }else{ txData.f = 'monitor_edit_failed' @@ -1640,15 +1657,27 @@ module.exports = function(s,config,lang){ if(notFound === false){ var sqlQuery = 'SELECT * FROM Monitors WHERE ke=? AND ' var monitorQuery = [] - var sqlQueryValues = [groupKey] var monitorPresets = {} + var didOne = false; preset.details.monitors.forEach(function(monitor){ - monitorQuery.push('mid=?') - sqlQueryValues.push(monitor.mid) + const whereConditions = {} + if(!didOne){ + didOne = true + whereConditions.ke = groupKey + monitorQuery.push(['ke','=',groupKey]) + }else{ + monitorQuery.push(['or','ke','=',groupKey]) + } + monitorQuery.push(['mid','=',monitor.mid]) monitorPresets[monitor.mid] = monitor }) - sqlQuery += '('+monitorQuery.join(' OR ')+')' - s.sqlQuery(sqlQuery,sqlQueryValues,function(err,monitors){ + s.knexQuery({ + action: "select", + columns: "*", + table: "Monitors", + where: monitorQuery + }).asCallback(function(err,monitors){ + console.log(err,monitors) if(monitors && monitors[0]){ monitors.forEach(function(monitor){ s.checkDetails(monitor) From 5db94d1e98e200f92c889807dafd2cf8d2f53239 Mon Sep 17 00:00:00 2001 From: Moe Date: Wed, 8 Jul 2020 23:11:43 -0700 Subject: [PATCH 006/175] sqlQuery Conversion : auth.js --- libs/auth.js | 51 ++++++++++++++++++++++++++++++++++++++++++++++----- libs/sql.js | 2 +- 2 files changed, 47 insertions(+), 6 deletions(-) diff --git a/libs/auth.js b/libs/auth.js index a4ce1b32..a5e01748 100644 --- a/libs/auth.js +++ b/libs/auth.js @@ -8,14 +8,30 @@ module.exports = function(s,config,lang){ // var getUserByUid = function(params,columns,callback){ if(!columns)columns = '*' - s.sqlQuery(`SELECT ${columns} FROM Users WHERE uid=? AND ke=?`,[params.uid,params.ke],function(err,r){ + s.knexQuery({ + action: "select", + columns: columns, + table: "Users", + where: [ + ['uid','=',params.uid], + ['ke','=',params.ke], + ] + }).asCallback(function(err,r) { if(!r)r = [] var user = r[0] callback(err,user) }) } var getUserBySessionKey = function(params,callback){ - s.sqlQuery('SELECT * FROM Users WHERE auth=? AND ke=?',[params.auth,params.ke],function(err,r){ + s.knexQuery({ + action: "select", + columns: '*', + table: "Users", + where: [ + ['auth','=',params.auth], + ['ke','=',params.ke], + ] + }).asCallback(function(err,r) { if(!r)r = [] var user = r[0] callback(err,user) @@ -23,7 +39,17 @@ module.exports = function(s,config,lang){ } var loginWithUsernameAndPassword = function(params,columns,callback){ if(!columns)columns = '*' - s.sqlQuery(`SELECT ${columns} FROM Users WHERE mail=? AND (pass=? OR pass=?) LIMIT 1`,[params.username,params.password,s.createHash(params.password)],function(err,r){ + s.knexQuery({ + action: "select", + columns: columns, + table: "Users", + where: [ + ['mail','=',params.username], + ['pass','=',params.password], + ['or','mail','=',params.username], + ['pass','=',s.createHash(params.password)], + ] + }).limit(1).asCallback(function(err,r) { if(!r)r = [] var user = r[0] callback(err,user) @@ -31,7 +57,15 @@ module.exports = function(s,config,lang){ } var getApiKey = function(params,columns,callback){ if(!columns)columns = '*' - s.sqlQuery(`SELECT ${columns} FROM API WHERE code=? AND ke=?`,[params.auth,params.ke],function(err,r){ + s.knexQuery({ + action: "select", + columns: columns, + table: "API", + where: [ + ['code','=',params.auth], + ['ke','=',params.ke], + ] + }).asCallback(function(err,r) { if(!r)r = [] var apiKey = r[0] callback(err,apiKey) @@ -226,7 +260,14 @@ module.exports = function(s,config,lang){ } var foundUser = function(){ if(params.users === true){ - s.sqlQuery('SELECT * FROM Users WHERE details NOT LIKE ?',['%"sub"%'],function(err,r) { + s.knexQuery({ + action: "select", + columns: columns, + table: "Users", + where: [ + ['details','NOT LIKE','%"sub"%'], + ] + }).asCallback(function(err,r) { adminUsersSelected = r success() }) diff --git a/libs/sql.js b/libs/sql.js index df28791b..cca18a6a 100644 --- a/libs/sql.js +++ b/libs/sql.js @@ -73,7 +73,7 @@ module.exports = function(s,config){ var dbQuery switch(options.action){ case'select': - if(!options.columns)options.columns = '*' + !options.columns ? '*' : options.columns.indexOf(',') > -1 ? options.columns.split(',') : options.columns; dbQuery = s.databaseEngine.select(...options.columns).from(options.table) break; case'update': From 477d756befe382b8e4c18ba0f924aec23411220b Mon Sep 17 00:00:00 2001 From: Moe Date: Thu, 9 Jul 2020 07:57:54 -0700 Subject: [PATCH 007/175] sqlQuery Conversion : make asCallback inside knexQuery --- libs/auth.js | 13 +++++++------ libs/monitor.js | 4 ++-- libs/startup.js | 14 +++++++------- 3 files changed, 16 insertions(+), 15 deletions(-) diff --git a/libs/auth.js b/libs/auth.js index a5e01748..d16e37d7 100644 --- a/libs/auth.js +++ b/libs/auth.js @@ -16,7 +16,7 @@ module.exports = function(s,config,lang){ ['uid','=',params.uid], ['ke','=',params.ke], ] - }).asCallback(function(err,r) { + },function(err,r) { if(!r)r = [] var user = r[0] callback(err,user) @@ -31,7 +31,7 @@ module.exports = function(s,config,lang){ ['auth','=',params.auth], ['ke','=',params.ke], ] - }).asCallback(function(err,r) { + },function(err,r) { if(!r)r = [] var user = r[0] callback(err,user) @@ -48,8 +48,9 @@ module.exports = function(s,config,lang){ ['pass','=',params.password], ['or','mail','=',params.username], ['pass','=',s.createHash(params.password)], - ] - }).limit(1).asCallback(function(err,r) { + ], + limit: 1 + },function(err,r) { if(!r)r = [] var user = r[0] callback(err,user) @@ -65,7 +66,7 @@ module.exports = function(s,config,lang){ ['code','=',params.auth], ['ke','=',params.ke], ] - }).asCallback(function(err,r) { + },function(err,r) { if(!r)r = [] var apiKey = r[0] callback(err,apiKey) @@ -267,7 +268,7 @@ module.exports = function(s,config,lang){ where: [ ['details','NOT LIKE','%"sub"%'], ] - }).asCallback(function(err,r) { + },function(err,r) { adminUsersSelected = r success() }) diff --git a/libs/monitor.js b/libs/monitor.js index f11daaf1..abb2b6c5 100644 --- a/libs/monitor.js +++ b/libs/monitor.js @@ -1410,7 +1410,7 @@ module.exports = function(s,config,lang){ ['ke','=',form.ke], ['mid','=',form.mid], ] - }).asCallback(function(err,r) { + },function(err,r) { var affectMonitor = false var monitorQuery = {} var txData = { @@ -1676,7 +1676,7 @@ module.exports = function(s,config,lang){ columns: "*", table: "Monitors", where: monitorQuery - }).asCallback(function(err,monitors){ + },function(err,monitors){ console.log(err,monitors) if(monitors && monitors[0]){ monitors.forEach(function(monitor){ diff --git a/libs/startup.js b/libs/startup.js index cee5c69b..2b5261b9 100644 --- a/libs/startup.js +++ b/libs/startup.js @@ -47,7 +47,7 @@ module.exports = function(s,config,lang,io){ action: "select", columns: "*", table: "Monitors", - }).asCallback(function(err,monitors) { + },function(err,monitors) { foundMonitors = monitors if(err){s.systemLog(err)} if(monitors && monitors[0]){ @@ -127,7 +127,7 @@ module.exports = function(s,config,lang,io){ ['ke','=',user.ke], ['status','!=',0], ] - }).asCallback(function(err,videos) { + },function(err,videos) { s.knexQuery({ action: "select", columns: "*", @@ -135,7 +135,7 @@ module.exports = function(s,config,lang,io){ where: [ ['ke','=',user.ke], ] - }).asCallback(function(err,timelapseFrames) { + },function(err,timelapseFrames) { s.knexQuery({ action: "select", columns: "*", @@ -143,7 +143,7 @@ module.exports = function(s,config,lang,io){ where: [ ['ke','=',user.ke], ] - }).asCallback(function(err,files) { + },function(err,files) { var usedSpaceVideos = 0 var usedSpaceTimelapseFrames = 0 var usedSpaceFilebin = 0 @@ -214,7 +214,7 @@ module.exports = function(s,config,lang,io){ ['ke','=',user.ke], ['status','!=',0], ] - }).asCallback(function(err,videos) { + },function(err,videos) { if(videos && videos[0]){ videos.forEach(function(video){ var storageType = JSON.parse(video.details).type @@ -241,7 +241,7 @@ module.exports = function(s,config,lang,io){ where: [ ['ke','=',user.ke], ] - }).asCallback(function(err,frames) { + },function(err,frames) { if(frames && frames[0]){ frames.forEach(function(frame){ var storageType = JSON.parse(frame.details).type @@ -332,7 +332,7 @@ module.exports = function(s,config,lang,io){ where: [ ['details','NOT LIKE','%"sub"%'] ] - }).asCallback(function(err,users) { + },function(err,users) { if(users && users[0]){ users.forEach(function(user){ checkedAdminUsers[user.ke] = user From 0f73187cb3a470f80c3283e6aed7392839244581 Mon Sep 17 00:00:00 2001 From: Moe Date: Thu, 9 Jul 2020 07:58:02 -0700 Subject: [PATCH 008/175] sqlQuery Conversion : add limit and orderBy --- libs/sql.js | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/libs/sql.js b/libs/sql.js index cca18a6a..eab21521 100644 --- a/libs/sql.js +++ b/libs/sql.js @@ -61,7 +61,7 @@ module.exports = function(s,config){ .raw(data.query,data.values) .asCallback(callback) }, 4); - const knexQuery = (options) => { + const knexQuery = (options,callback) => { if(config.debugLog === true){ s.debugLog('s.knexQuery QUERY',options) } @@ -109,9 +109,16 @@ module.exports = function(s,config){ } }) } - if(options.update || options.insert){ + if(options.orderBy){ + dbQuery.orderBy(...options.orderBy) + } + if(options.limit){ + dbQuery.limit(options.limit) + } + if(callback || options.update || options.insert){ dbQuery.asCallback(function(err,r) { if(err)console.log(err) + if(callback)callback(err,r) }) } return dbQuery From c311aefec4ff9d8a0f3d6c5a38f47c8be24e1467 Mon Sep 17 00:00:00 2001 From: Dave Hayes Date: Thu, 9 Jul 2020 13:52:49 -0700 Subject: [PATCH 009/175] Add framework.pgsql --- package.json | 20 ++-- sql/framework.pgsql | 218 ++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 229 insertions(+), 9 deletions(-) create mode 100644 sql/framework.pgsql diff --git a/package.json b/package.json index cb8c1781..2872e0dd 100644 --- a/package.json +++ b/package.json @@ -23,6 +23,7 @@ "discord.js": "^11.3.2", "ejs": "^2.5.5", "express": "^4.16.4", + "express-fileupload": "^1.1.6-alpha.6", "ftp-srv": "^4.3.1", "http-proxy": "^1.17.0", "jsonfile": "^3.0.1", @@ -34,18 +35,20 @@ "node-onvif": "^0.1.4", "node-ssh": "^5.1.2", "nodemailer": "^4.0.1", + "npm": "^6.14.6", "pam-diff": "^1.0.0", "path": "^0.12.7", + "pg": "^8.2.2", "pipe2pam": "^0.6.2", + "pm2": "^3.0.0", "request": "^2.88.0", "sat": "^0.7.1", "shinobi-sound-detection": "^0.1.8", "smtp-server": "^3.5.0", "socket.io": "^2.2.0", "socket.io-client": "^2.2.0", - "webdav-fs": "^1.11.0", - "express-fileupload": "^1.1.6-alpha.6", - "tree-kill":"1.2.2" + "tree-kill": "1.2.2", + "webdav-fs": "^1.11.0" }, "devDependencies": {}, "bin": "camera.js", @@ -63,13 +66,12 @@ "targets": [ "node12" ], - "scripts": [ - ], + "scripts": [], "assets": [ - "definitions/*", - "languages/*", - "web/*", - "test/*" + "definitions/*", + "languages/*", + "web/*", + "test/*" ] } } diff --git a/sql/framework.pgsql b/sql/framework.pgsql new file mode 100644 index 00000000..a37d46d3 --- /dev/null +++ b/sql/framework.pgsql @@ -0,0 +1,218 @@ +/* + * PostgresSQL rewrite of framework.sql - dave@dream-tech.com + * Placed into open source, no license required here unless you want one, licenses and lawyers + * are the primary bane of good software development. :) + * + * Trigger code lifted from stack overflow here: + * https://stackoverflow.com/questions/9556474/how-do-i-automatically-update-a-timestamp-in-postgresql + * + * Summary of changes: + * a) Removed mysql cruft and comments, no need for 'use' + * b) Removed create database statement (I can put one back but usually I create dbs using postgres command line tools: + * e.g. 'createdb foo') + * c) Removed all cases of int(\d+) and replaced with just int, postgres does not support those + * d) Removed ENGINE=InnoDB + * e) Removed default charset statements, Postgresql automatically supports 4-byte UTF8 at database createion + * f) Removed backtick quotes and added double quotes + * g) All timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP replaced with triggers + * and the ON UPDATE portion removed as postgres doesn't support this sadly + * h) tinytext/longtest is changed to just text, generally postgres does a good job of managing arbitrary text columns + * i) Enums created the Postgres way by creating a type + * + * Here's my DB create flow: + * 1) become the account that controls pgsql (pgsql superuser) + * 2) from that shell prompt, say: + * createuser -p shinobi + * Enter a secure password after this, twice. + * 3) from same shell prompt say: + * createdb --owner shinobi --encoding='utf-8' shinobi + * 4) now from same shell prompt you can do + * psql shinobi Date: Thu, 9 Jul 2020 14:45:16 -0700 Subject: [PATCH 010/175] Put back package.json --- package.json | 20 +++++++++----------- 1 file changed, 9 insertions(+), 11 deletions(-) diff --git a/package.json b/package.json index 2872e0dd..cb8c1781 100644 --- a/package.json +++ b/package.json @@ -23,7 +23,6 @@ "discord.js": "^11.3.2", "ejs": "^2.5.5", "express": "^4.16.4", - "express-fileupload": "^1.1.6-alpha.6", "ftp-srv": "^4.3.1", "http-proxy": "^1.17.0", "jsonfile": "^3.0.1", @@ -35,20 +34,18 @@ "node-onvif": "^0.1.4", "node-ssh": "^5.1.2", "nodemailer": "^4.0.1", - "npm": "^6.14.6", "pam-diff": "^1.0.0", "path": "^0.12.7", - "pg": "^8.2.2", "pipe2pam": "^0.6.2", - "pm2": "^3.0.0", "request": "^2.88.0", "sat": "^0.7.1", "shinobi-sound-detection": "^0.1.8", "smtp-server": "^3.5.0", "socket.io": "^2.2.0", "socket.io-client": "^2.2.0", - "tree-kill": "1.2.2", - "webdav-fs": "^1.11.0" + "webdav-fs": "^1.11.0", + "express-fileupload": "^1.1.6-alpha.6", + "tree-kill":"1.2.2" }, "devDependencies": {}, "bin": "camera.js", @@ -66,12 +63,13 @@ "targets": [ "node12" ], - "scripts": [], + "scripts": [ + ], "assets": [ - "definitions/*", - "languages/*", - "web/*", - "test/*" + "definitions/*", + "languages/*", + "web/*", + "test/*" ] } } From 21ea4d804f708edd7a26912410cb630b15db15b4 Mon Sep 17 00:00:00 2001 From: Moe Date: Thu, 9 Jul 2020 22:48:34 -0700 Subject: [PATCH 011/175] sqlQuery Conversion : basic, events, notifications, scheduler, socketio --- libs/basic.js | 10 +- libs/events.js | 11 +- libs/notification.js | 20 +- libs/scheduler.js | 66 +++- libs/socketio.js | 824 ++++++++++++++++--------------------------- 5 files changed, 393 insertions(+), 538 deletions(-) diff --git a/libs/basic.js b/libs/basic.js index c5903aa1..62187161 100644 --- a/libs/basic.js +++ b/libs/basic.js @@ -214,7 +214,15 @@ module.exports = function(s,config){ if(!e){e=''} if(config.systemLog===true){ if(typeof q==='string'&&s.databaseEngine){ - s.sqlQuery('INSERT INTO Logs (ke,mid,info) VALUES (?,?,?)',['$','$SYSTEM',s.s({type:q,msg:w})]); + s.knexQuery({ + action: "insert", + table: "Logs", + insert: { + ke: '$', + mid: '$SYSTEM', + info: s.s({type:q,msg:w}), + } + }) s.tx({f:'log',log:{time:s.timeObject(),ke:'$',mid:'$SYSTEM',time:s.timeObject(),info:s.s({type:q,msg:w})}},'$'); } return console.log(s.timeObject().format(),q,w,e) diff --git a/libs/events.js b/libs/events.js index 43c26792..3d542cca 100644 --- a/libs/events.js +++ b/libs/events.js @@ -394,7 +394,16 @@ module.exports = function(s,config,lang){ } //save this detection result in SQL, only coords. not image. if(forceSave || (filter.save && currentConfig.detector_save === '1')){ - s.sqlQuery('INSERT INTO Events (ke,mid,details,time) VALUES (?,?,?,?)',[d.ke,d.id,detailString,eventTime]) + s.knexQuery({ + action: "insert", + table: "Events", + insert: { + ke: d.ke, + mid: d.id, + details: detailString, + time: eventTime, + } + }) } if(currentConfig.detector === '1' && currentConfig.detector_notrigger === '1'){ s.setNoEventsDetector(s.group[d.ke].rawMonitorConfigurations[d.id]) diff --git a/libs/notification.js b/libs/notification.js index 73cb66db..9ef37aa3 100644 --- a/libs/notification.js +++ b/libs/notification.js @@ -207,7 +207,15 @@ module.exports = function(s,config,lang){ var onDetectorNoTriggerTimeoutForEmail = function(e){ //e = monitor object if(config.mail && e.details.detector_notrigger_mail === '1'){ - s.sqlQuery('SELECT mail FROM Users WHERE ke=? AND details NOT LIKE ?',[e.ke,'%"sub"%'],function(err,r){ + s.knexQuery({ + action: "select", + columns: "mail", + table: "Users", + where: [ + ['ke','=',e.ke], + ['details','NOT LIKE','%"sub"%'], + ] + },function(err,r) { r = r[0] var mailOptions = { from: config.mail.from, // sender address @@ -283,7 +291,15 @@ module.exports = function(s,config,lang){ } var onEventTriggerForEmail = function(d,filter){ if(filter.mail && config.mail && !s.group[d.ke].activeMonitors[d.id].detector_mail){ - s.sqlQuery('SELECT mail FROM Users WHERE ke=? AND details NOT LIKE ?',[d.ke,'%"sub"%'],function(err,r){ + s.knexQuery({ + action: "select", + columns: "mail", + table: "Users", + where: [ + ['ke','=',d.ke], + ['details','NOT LIKE','%"sub"%'], + ] + },function(err,r) { r=r[0]; var detector_mail_timeout if(!d.mon.details.detector_mail_timeout||d.mon.details.detector_mail_timeout===''){ diff --git a/libs/scheduler.js b/libs/scheduler.js index ddd2afac..05fde71b 100644 --- a/libs/scheduler.js +++ b/libs/scheduler.js @@ -3,7 +3,11 @@ module.exports = function(s,config,lang,app,io){ //Get all Schedules s.getAllSchedules = function(callback){ s.schedules = {} - s.sqlQuery('SELECT * FROM Schedules',function(err,rows){ + s.knexQuery({ + action: "select", + columns: "*", + table: "Schedules" + },function(err,rows) { rows.forEach(function(schedule){ s.updateSchedule(schedule) }) @@ -141,7 +145,16 @@ module.exports = function(s,config,lang,app,io){ // s.findSchedule = function(groupKey,name,callback){ //presetQueryVals = [ke, type, name] - s.sqlQuery("SELECT * FROM Schedules WHERE ke=? AND name=? LIMIT 1",[groupKey,name],function(err,schedules){ + s.knexQuery({ + action: "select", + columns: "*", + table: "Schedules", + where: [ + ['ke','=',groupKey], + ['name','=',name], + ], + limit: 1 + },function(err,schedules) { var schedule var notFound = false if(schedules && schedules[0]){ @@ -184,13 +197,18 @@ module.exports = function(s,config,lang,app,io){ s.closeJsonResponse(res,endData) return } - var theQuery = "SELECT * FROM Schedules WHERE ke=?" - var theQueryValues = [req.params.ke] + var whereQuery = [ + ['ke','=',req.params.ke] + ] if(req.params.name){ - theQuery += ' AND name=?' - theQueryValues.push(req.params.name) + whereQuery.push(['name','=',req.params.name]) } - s.sqlQuery(theQuery,theQueryValues,function(err,schedules){ + s.knexQuery({ + action: "select", + columns: "*", + table: "Schedules", + where: whereQuery, + },function(err,schedules) { endData.ok = true schedules = schedules || [] schedules.forEach(function(schedule){ @@ -240,7 +258,11 @@ module.exports = function(s,config,lang,app,io){ end: form.end, enabled: form.enabled } - s.sqlQuery('INSERT INTO Schedules ('+Object.keys(insertData).join(',')+') VALUES (?,?,?,?,?,?)',Object.values(insertData)) + s.knexQuery({ + action: "insert", + table: "Schedules", + insert: insertData + }) s.tx({ f: 'add_schedule', insertData: insertData, @@ -253,14 +275,23 @@ module.exports = function(s,config,lang,app,io){ details: s.stringJSON(form.details), start: form.start, end: form.end, - enabled: form.enabled, - ke: req.params.ke, - name: req.params.name + enabled: form.enabled } - s.sqlQuery('UPDATE Schedules SET details=?,start=?,end=?,enabled=? WHERE ke=? AND name=?',Object.values(insertData)) + s.knexQuery({ + action: "update", + table: "Monitors", + update: insertData, + where: [ + ['ke','=',req.params.ke], + ['name','=',req.params.name], + ] + }) s.tx({ f: 'edit_schedule', - insertData: insertData, + insertData: Object.assign(insertData,{ + ke: req.params.ke, + name: req.params.name, + }), ke: req.params.ke, name: req.params.name },'GRP_'+req.params.ke) @@ -283,7 +314,14 @@ module.exports = function(s,config,lang,app,io){ endData.msg = user.lang['Schedule Configuration Not Found'] s.closeJsonResponse(res,endData) }else{ - s.sqlQuery('DELETE FROM Schedules WHERE ke=? AND name=?',[req.params.ke,req.params.name],function(err){ + s.knexQuery({ + action: "delete", + table: "Schedules", + where: [ + ['ke','=',req.params.ke], + ['name','=',req.params.name], + ] + },function(err){ if(!err){ endData.msg = lang["Deleted Schedule Configuration"] endData.ok = true diff --git a/libs/socketio.js b/libs/socketio.js index 1c4ac60e..386a6a68 100644 --- a/libs/socketio.js +++ b/libs/socketio.js @@ -51,6 +51,87 @@ module.exports = function(s,config,lang,io){ } } + const streamConnectionAuthentication = (options) => { + return new Promise( (resolve,reject) => { + s.knexQuery({ + action: "select", + columns: "ke,uid,auth,mail,details", + table: "Users", + where: [ + ['ke','=',options.ke], + ['auth','=',options.auth], + ['uid','=',options.uid], + ] + },function(err,r) { + if(r&&r[0]){ + resolve(r) + }else{ + s.knexQuery({ + action: "select", + columns: "*", + table: "API", + where: [ + ['ke','=',options.ke], + ['code','=',options.auth], + ['uid','=',options.uid], + ] + },function(err,r) { + if(r && r[0]){ + r = r[0] + r.details = JSON.parse(r.details) + if(r.details.auth_socket === '1'){ + s.knexQuery({ + action: "select", + columns: "ke,uid,auth,mail,details", + table: "Users", + where: [ + ['ke','=',options.ke], + ['uid','=',options.uid], + ] + },function(err,r) { + if(r && r[0]){ + resolve(r) + }else{ + reject('User not found') + } + }) + }else{ + reject('Permissions for this key do not allow authentication with Websocket') + } + }else{ + reject('Not an API key') + } + }) + } + }) + }) + } + + const validatedAndBindAuthenticationToSocketConnection = (cn,d,removeListenerOnDisconnect) => { + if(!d.channel)d.channel = 'MAIN'; + cn.ke = d.ke, + cn.uid = d.uid, + cn.auth = d.auth; + cn.channel = d.channel; + cn.removeListenerOnDisconnect = removeListenerOnDisconnect; + cn.socketVideoStream = d.id; + } + + const createStreamEmitter = (d) => { + var Emitter,chunkChannel + if(!d.channel){ + Emitter = s.group[d.ke].activeMonitors[d.id].emitter + chunkChannel = 'MAIN' + }else{ + Emitter = s.group[d.ke].activeMonitors[d.id].emitterChannel[parseInt(d.channel)+config.pipeAddition] + chunkChannel = parseInt(d.channel)+config.pipeAddition + } + if(!Emitter){ + cn.disconnect();return; + } + return Emitter + } + ////socket controller io.on('connection', function (cn) { var tx; @@ -64,30 +145,14 @@ module.exports = function(s,config,lang,io){ return new Date().toISOString(); } var tx=function(z){cn.emit('data',z);} - d.failed=function(msg){ + const onFail = (msg) => { tx({f:'stop_reconnect',msg:msg,token_used:d.auth,ke:d.ke}); cn.disconnect(); } - d.success=function(r){ - r=r[0]; - var Emitter,chunkChannel - if(!d.channel){ - Emitter = s.group[d.ke].activeMonitors[d.id].emitter - chunkChannel = 'MAIN' - }else{ - Emitter = s.group[d.ke].activeMonitors[d.id].emitterChannel[parseInt(d.channel)+config.pipeAddition] - chunkChannel = parseInt(d.channel)+config.pipeAddition - } - if(!Emitter){ - cn.disconnect();return; - } - if(!d.channel)d.channel = 'MAIN'; - cn.ke=d.ke, - cn.uid=d.uid, - cn.auth=d.auth; - cn.channel=d.channel; - cn.removeListenerOnDisconnect=true; - cn.socketVideoStream=d.id; + const onSuccess = (r) => { + r = r[0]; + const Emitter = createStreamEmitter(d) + validatedAndBindAuthenticationToSocketConnection(cn,d,true) var contentWriter cn.closeSocketVideoStream = function(){ Emitter.removeListener('data', contentWriter); @@ -98,33 +163,9 @@ module.exports = function(s,config,lang,io){ } //check if auth key is user's temporary session key if(s.group[d.ke]&&s.group[d.ke].users&&s.group[d.ke].users[d.auth]){ - d.success(s.group[d.ke].users[d.auth]); + onSuccess(s.group[d.ke].users[d.auth]); }else{ - s.sqlQuery('SELECT ke,uid,auth,mail,details FROM Users WHERE ke=? AND auth=? AND uid=?',[d.ke,d.auth,d.uid],function(err,r) { - if(r&&r[0]){ - d.success(r) - }else{ - s.sqlQuery('SELECT * FROM API WHERE ke=? AND code=? AND uid=?',[d.ke,d.auth,d.uid],function(err,r) { - if(r&&r[0]){ - r=r[0] - r.details=JSON.parse(r.details) - if(r.details.auth_socket==='1'){ - s.sqlQuery('SELECT ke,uid,auth,mail,details FROM Users WHERE ke=? AND uid=?',[r.ke,r.uid],function(err,r) { - if(r&&r[0]){ - d.success(r) - }else{ - d.failed('User not found') - } - }) - }else{ - d.failed('Permissions for this key do not allow authentication with Websocket') - } - }else{ - d.failed('Not an API key') - } - }) - } - }) + streamConnectionAuthentication(d).then(onSuccess).catch(onFail) } }) //unique Base64 socket stream @@ -137,30 +178,14 @@ module.exports = function(s,config,lang,io){ return new Date().toISOString(); } var tx=function(z){cn.emit('data',z);} - d.failed=function(msg){ + const onFail = (msg) => { tx({f:'stop_reconnect',msg:msg,token_used:d.auth,ke:d.ke}); cn.disconnect(); } - d.success=function(r){ - r=r[0]; - var Emitter,chunkChannel - if(!d.channel){ - Emitter = s.group[d.ke].activeMonitors[d.id].emitter - chunkChannel = 'MAIN' - }else{ - Emitter = s.group[d.ke].activeMonitors[d.id].emitterChannel[parseInt(d.channel)+config.pipeAddition] - chunkChannel = parseInt(d.channel)+config.pipeAddition - } - if(!Emitter){ - cn.disconnect();return; - } - if(!d.channel)d.channel = 'MAIN'; - cn.ke=d.ke, - cn.uid=d.uid, - cn.auth=d.auth; - cn.channel=d.channel; - cn.removeListenerOnDisconnect=true; - cn.socketVideoStream=d.id; + const onSuccess = (r) => { + r = r[0]; + const Emitter = createStreamEmitter(d) + validatedAndBindAuthenticationToSocketConnection(cn,d,true) var contentWriter cn.closeSocketVideoStream = function(){ Emitter.removeListener('data', contentWriter); @@ -171,33 +196,9 @@ module.exports = function(s,config,lang,io){ } //check if auth key is user's temporary session key if(s.group[d.ke]&&s.group[d.ke].users&&s.group[d.ke].users[d.auth]){ - d.success(s.group[d.ke].users[d.auth]); + onSuccess(s.group[d.ke].users[d.auth]); }else{ - s.sqlQuery('SELECT ke,uid,auth,mail,details FROM Users WHERE ke=? AND auth=? AND uid=?',[d.ke,d.auth,d.uid],function(err,r) { - if(r&&r[0]){ - d.success(r) - }else{ - s.sqlQuery('SELECT * FROM API WHERE ke=? AND code=? AND uid=?',[d.ke,d.auth,d.uid],function(err,r) { - if(r&&r[0]){ - r=r[0] - r.details=JSON.parse(r.details) - if(r.details.auth_socket==='1'){ - s.sqlQuery('SELECT ke,uid,auth,mail,details FROM Users WHERE ke=? AND uid=?',[r.ke,r.uid],function(err,r) { - if(r&&r[0]){ - d.success(r) - }else{ - d.failed('User not found') - } - }) - }else{ - d.failed('Permissions for this key do not allow authentication with Websocket') - } - }else{ - d.failed('Not an API key') - } - }) - } - }) + streamConnectionAuthentication(d).then(onSuccess).catch(onFail) } }) //unique FLV socket stream @@ -210,30 +211,14 @@ module.exports = function(s,config,lang,io){ return new Date().toISOString(); } var tx=function(z){cn.emit('data',z);} - d.failed=function(msg){ + const onFail = (msg) => { tx({f:'stop_reconnect',msg:msg,token_used:d.auth,ke:d.ke}); cn.disconnect(); } - d.success=function(r){ + const onSuccess = (r) => { r=r[0]; - var Emitter,chunkChannel - if(!d.channel){ - Emitter = s.group[d.ke].activeMonitors[d.id].emitter - chunkChannel = 'MAIN' - }else{ - Emitter = s.group[d.ke].activeMonitors[d.id].emitterChannel[parseInt(d.channel)+config.pipeAddition] - chunkChannel = parseInt(d.channel)+config.pipeAddition - } - if(!Emitter){ - cn.disconnect();return; - } - if(!d.channel)d.channel = 'MAIN'; - cn.ke=d.ke, - cn.uid=d.uid, - cn.auth=d.auth; - cn.channel=d.channel; - cn.removeListenerOnDisconnect=true; - cn.socketVideoStream=d.id; + const Emitter = createStreamEmitter(d) + validatedAndBindAuthenticationToSocketConnection(cn,d,true) var contentWriter cn.closeSocketVideoStream = function(){ Emitter.removeListener('data', contentWriter); @@ -244,33 +229,9 @@ module.exports = function(s,config,lang,io){ }) } if(s.group[d.ke] && s.group[d.ke].users && s.group[d.ke].users[d.auth]){ - d.success(s.group[d.ke].users[d.auth]); + onSuccess(s.group[d.ke].users[d.auth]); }else{ - s.sqlQuery('SELECT ke,uid,auth,mail,details FROM Users WHERE ke=? AND auth=? AND uid=?',[d.ke,d.auth,d.uid],function(err,r) { - if(r&&r[0]){ - d.success(r) - }else{ - s.sqlQuery('SELECT * FROM API WHERE ke=? AND code=? AND uid=?',[d.ke,d.auth,d.uid],function(err,r) { - if(r&&r[0]){ - r=r[0] - r.details=JSON.parse(r.details) - if(r.details.auth_socket==='1'){ - s.sqlQuery('SELECT ke,uid,auth,mail,details FROM Users WHERE ke=? AND uid=?',[r.ke,r.uid],function(err,r) { - if(r&&r[0]){ - d.success(r) - }else{ - d.failed('User not found') - } - }) - }else{ - d.failed('Permissions for this key do not allow authentication with Websocket') - } - }else{ - d.failed('Not an API key') - } - }) - } - }) + streamConnectionAuthentication(d).then(onSuccess).catch(onFail) } }) //unique MP4 socket stream @@ -283,29 +244,13 @@ module.exports = function(s,config,lang,io){ return new Date().toISOString(); } var tx=function(z){cn.emit('data',z);} - d.failed=function(msg){ + const onFail = (msg) => { tx({f:'stop_reconnect',msg:msg,token_used:d.auth,ke:d.ke}); cn.disconnect(); } - d.success=function(r){ - r=r[0]; - var Emitter,chunkChannel - if(!d.channel){ - Emitter = s.group[d.ke].activeMonitors[d.id].emitter - chunkChannel = 'MAIN' - }else{ - Emitter = s.group[d.ke].activeMonitors[d.id].emitterChannel[parseInt(d.channel)+config.pipeAddition] - chunkChannel = parseInt(d.channel)+config.pipeAddition - } - if(!Emitter){ - cn.disconnect();return; - } - if(!d.channel)d.channel = 'MAIN'; - cn.ke=d.ke, - cn.uid=d.uid, - cn.auth=d.auth; - cn.channel=d.channel; - cn.socketVideoStream=d.id; + const onSuccess = (r) => { + r = r[0]; + validatedAndBindAuthenticationToSocketConnection(cn,d) var mp4frag = s.group[d.ke].activeMonitors[d.id].mp4frag[d.channel]; var onInitialized = () => { cn.emit('mime', mp4frag.mime); @@ -364,33 +309,9 @@ module.exports = function(s,config,lang,io){ }) } if(s.group[d.ke]&&s.group[d.ke].users&&s.group[d.ke].users[d.auth]){ - d.success(s.group[d.ke].users[d.auth]); + onSuccess(s.group[d.ke].users[d.auth]); }else{ - s.sqlQuery('SELECT ke,uid,auth,mail,details FROM Users WHERE ke=? AND auth=? AND uid=?',[d.ke,d.auth,d.uid],function(err,r) { - if(r&&r[0]){ - d.success(r) - }else{ - s.sqlQuery('SELECT * FROM API WHERE ke=? AND code=? AND uid=?',[d.ke,d.auth,d.uid],function(err,r) { - if(r&&r[0]){ - r=r[0] - r.details=JSON.parse(r.details) - if(r.details.auth_socket==='1'){ - s.sqlQuery('SELECT ke,uid,auth,mail,details FROM Users WHERE ke=? AND uid=?',[r.ke,r.uid],function(err,r) { - if(r&&r[0]){ - d.success(r) - }else{ - d.failed('User not found') - } - }) - }else{ - d.failed('Permissions for this key do not allow authentication with Websocket') - } - }else{ - d.failed('Not an API key') - } - }) - } - }) + streamConnectionAuthentication(d).then(onSuccess).catch(onFail) } }) //main socket control functions @@ -398,9 +319,12 @@ module.exports = function(s,config,lang,io){ if(!cn.ke&&d.f==='init'){//socket login cn.ip=cn.request.connection.remoteAddress; tx=function(z){if(!z.ke){z.ke=cn.ke;};cn.emit('f',z);} - d.failed=function(){tx({ok:false,msg:'Not Authorized',token_used:d.auth,ke:d.ke});cn.disconnect();} - d.success=function(r){ - r=r[0];cn.join('GRP_'+d.ke);cn.join('CPU'); + const onFail = (msg) => { + tx({ok:false,msg:'Not Authorized',token_used:d.auth,ke:d.ke});cn.disconnect(); + } + const onSuccess = (r) => { + r = r[0]; + cn.join('GRP_'+d.ke);cn.join('CPU'); cn.ke=d.ke, cn.uid=d.uid, cn.auth=d.auth; @@ -431,7 +355,15 @@ module.exports = function(s,config,lang,io){ s.tx({f:'user_status_change',ke:d.ke,uid:cn.uid,status:1,user:s.group[d.ke].users[d.auth]},'GRP_'+d.ke) s.sendDiskUsedAmountToClients(d) s.loadGroupApps(d) - s.sqlQuery('SELECT * FROM API WHERE ke=? AND uid=?',[d.ke,d.uid],function(err,rrr) { + s.knexQuery({ + action: "select", + columns: "*", + table: "API", + where: [ + ['ke','=',d.ke], + ['uid','=',d.uid], + ] + },function(err,rrr) { tx({ f:'init_success', users:s.group[d.ke].vid, @@ -443,7 +375,14 @@ module.exports = function(s,config,lang,io){ } }) try{ - s.sqlQuery('SELECT * FROM Monitors WHERE ke=?', [d.ke], function(err,r) { + s.knexQuery({ + action: "select", + columns: "*", + table: "Monitors", + where: [ + ['ke','=',d.ke], + ] + },function(err,r) { if(r && r[0]){ r.forEach(function(monitor){ s.cameraSendSnapshot({mid:monitor.mid,ke:monitor.ke,mon:monitor},{useIcon: true}) @@ -458,31 +397,7 @@ module.exports = function(s,config,lang,io){ extender(r,cn,d,tx) }) } - s.sqlQuery('SELECT ke,uid,auth,mail,details FROM Users WHERE ke=? AND auth=? AND uid=?',[d.ke,d.auth,d.uid],function(err,r) { - if(r&&r[0]){ - d.success(r) - }else{ - s.sqlQuery('SELECT * FROM API WHERE ke=? AND code=? AND uid=?',[d.ke,d.auth,d.uid],function(err,r) { - if(r&&r[0]){ - r=r[0] - r.details=JSON.parse(r.details) - if(r.details.auth_socket==='1'){ - s.sqlQuery('SELECT ke,uid,auth,mail,details FROM Users WHERE ke=? AND uid=?',[r.ke,r.uid],function(err,r) { - if(r&&r[0]){ - d.success(r) - }else{ - d.failed() - } - }) - }else{ - d.failed() - } - }else{ - d.failed() - } - }) - } - }) + streamConnectionAuthentication(d).then(onSuccess).catch(onFail) return; } if((d.id||d.uid||d.mid)&&cn.ke){ @@ -490,83 +405,71 @@ module.exports = function(s,config,lang,io){ switch(d.f){ case'monitorOrder': if(d.monitorOrder && d.monitorOrder instanceof Object){ - s.sqlQuery('SELECT details FROM Users WHERE uid=? AND ke=?',[cn.uid,cn.ke],function(err,r){ + const whereQuery = [ + ['ke','=',cn.ke], + ['uid','=',cn.uid], + ] + s.knexQuery({ + action: "details", + columns: "*", + table: "Users", + where: whereQuery + },function(err,r) { if(r && r[0]){ details = JSON.parse(r[0].details) details.monitorOrder = d.monitorOrder - s.sqlQuery('UPDATE Users SET details=? WHERE uid=? AND ke=?',[s.s(details),cn.uid,cn.ke]) + s.knexQuery({ + action: "update", + table: "Users", + update: { + details: s.s(details) + }, + where: whereQuery + }) } }) } break; case'monitorListOrder': if(d.monitorListOrder && d.monitorListOrder instanceof Object){ - s.sqlQuery('SELECT details FROM Users WHERE uid=? AND ke=?',[cn.uid,cn.ke],function(err,r){ + s.knexQuery({ + action: "details", + columns: "*", + table: "Users", + where: whereQuery + },function(err,r) { if(r && r[0]){ details = JSON.parse(r[0].details) details.monitorListOrder = d.monitorListOrder - s.sqlQuery('UPDATE Users SET details=? WHERE uid=? AND ke=?',[s.s(details),cn.uid,cn.ke]) + s.knexQuery({ + action: "update", + table: "Users", + update: { + details: s.s(details) + }, + where: whereQuery + }) } }) } break; - case'update': - if(!config.updateKey){ - tx({error:lang.updateKeyText1}); - return; - } - if(d.key===config.updateKey){ - exec('chmod +x '+s.mainDirectory+'/UPDATE.sh&&'+s.mainDirectory+'/UPDATE.sh',{detached: true}) - }else{ - tx({error:lang.updateKeyText2}); - } - break; - case'cron': - if(s.group[cn.ke]&&s.group[cn.ke].users[cn.auth].details&&!s.group[cn.ke].users[cn.auth].details.sub){ - s.tx({f:d.ff},s.cron.id) - } - break; - case'api': - switch(d.ff){ - case'delete': - d.set=[],d.ar=[]; - d.form.ke=cn.ke;d.form.uid=cn.uid;delete(d.form.ip); - if(!d.form.code){tx({f:'form_incomplete',form:'APIs',uid:cn.uid});return} - d.for=Object.keys(d.form); - d.for.forEach(function(v){ - d.set.push(v+'=?'),d.ar.push(d.form[v]); - }); - s.sqlQuery('DELETE FROM API WHERE '+d.set.join(' AND '),d.ar,function(err,r){ - if(!err){ - tx({f:'api_key_deleted',form:d.form,uid:cn.uid}); - delete(s.api[d.form.code]); - }else{ - s.systemLog('API Delete Error : '+e.ke+' : '+' : '+e.mid,err) - } - }) - break; - case'add': - d.set=[],d.qu=[],d.ar=[]; - d.form.ke=cn.ke,d.form.uid=cn.uid,d.form.code=s.gid(30); - d.for=Object.keys(d.form); - d.for.forEach(function(v){ - d.set.push(v),d.qu.push('?'),d.ar.push(d.form[v]); - }); - s.sqlQuery('INSERT INTO API ('+d.set.join(',')+') VALUES ('+d.qu.join(',')+')',d.ar,function(err,r){ - d.form.time=s.formattedTime(new Date,'YYYY-DD-MM HH:mm:ss'); - if(!err){tx({f:'api_key_added',form:d.form,uid:cn.uid});}else{s.systemLog(err)} - }); - break; - } - break; case'settings': switch(d.ff){ case'filters': switch(d.fff){ case'save':case'delete': - s.sqlQuery('SELECT details FROM Users WHERE ke=? AND uid=?',[d.ke,d.uid],function(err,r){ - if(r&&r[0]){ - r=r[0]; + s.knexQuery({ + action: "select", + columns: "details", + table: "Users", + where: [ + ['ke','=',d.ke], + ['uid','=',d.uid], + ], + limit: 1 + },function(err,r) { + if(r && r[0]){ + r = r[0]; d.d=JSON.parse(r.details); if(d.form.id===''){d.form.id=s.gid(5)} if(!d.d.filters)d.d.filters={}; @@ -576,9 +479,19 @@ module.exports = function(s,config,lang,io){ }else{ delete(d.d.filters[d.form.id]); } - s.sqlQuery('UPDATE Users SET details=? WHERE ke=? AND uid=?',[JSON.stringify(d.d),d.ke,d.uid],function(err,r){ + s.knexQuery({ + action: "update", + table: "Users", + update: { + details: JSON.stringify(d.d) + }, + where: [ + ['ke','=',d.ke], + ['uid','=',d.uid], + ] + },(err) => { tx({f:'filters_change',uid:d.uid,ke:d.ke,filters:d.d.filters}); - }); + }) } }) break; @@ -606,48 +519,56 @@ module.exports = function(s,config,lang,io){ if(!d.eventEndDate&&d.endDate){ d.eventEndDate = s.stringToSqlTime(d.endDate) } - var monitorQuery = '' - var monitorValues = [] + var monitorRestrictions = [] var permissions = s.group[d.ke].users[cn.auth].details; if(!d.mid){ - if(permissions.sub&&permissions.monitors&&permissions.allmonitors!=='1'){ - try{permissions.monitors=JSON.parse(permissions.monitors);}catch(er){} - var or = []; - permissions.monitors.forEach(function(v,n){ - or.push('mid=?'); - monitorValues.push(v) - }) - monitorQuery += ' AND ('+or.join(' OR ')+')' - } - }else if(!permissions.sub||permissions.allmonitors!=='0'||permissions.monitors.indexOf(d.mid)>-1){ - monitorQuery += ' and mid=?'; - monitorValues.push(d.mid) - } - var getEvents = function(callback){ - var eventQuery = 'SELECT * FROM Events WHERE ke=?'; - var eventQueryValues = [cn.ke]; - if(d.eventStartDate&&d.eventStartDate!==''){ - if(d.eventEndDate&&d.eventEndDate!==''){ - eventQuery+=' AND `time` >= ? AND `time` <= ?'; - eventQueryValues.push(d.eventStartDate) - eventQueryValues.push(d.eventEndDate) - }else{ - eventQuery+=' AND `time` >= ?'; - eventQueryValues.push(d.eventStartDate) + if(permissions.sub && permissions.monitors && permissions.allmonitors !== '1'){ + try{ + permissions.monitors = JSON.parse(permissions.monitors); + permissions.monitors.forEach(function(v,n){ + if(n === 0){ + monitorRestrictions.push(['mid','=',v]) + }else{ + monitorRestrictions.push(['or','mid','=',v]) + } + }) + }catch(er){ + console.log(er) } } - if(monitorValues.length>0){ - eventQuery += monitorQuery; - eventQueryValues = eventQueryValues.concat(monitorValues); + }else if(!permissions.sub||permissions.allmonitors!=='0'||permissions.monitors.indexOf(d.mid)>-1){ + monitorRestrictions.push(['mid','=',d.mid]) + } + console.log('monitorRestrictions',monitorRestrictions,monitorRestrictions.length) + var getEvents = function(callback){ + var eventWhereQuery = [ + ['ke','=',cn.ke], + ] + if(d.eventStartDate&&d.eventStartDate!==''){ + if(d.eventEndDate&&d.eventEndDate!==''){ + eventWhereQuery.push(['time','>=',d.eventStartDate]) + eventWhereQuery.push(['time','<=',d.eventEndDate]) + }else{ + eventWhereQuery.push(['time','>=',d.eventStartDate]) + } } - eventQuery+=' ORDER BY `time` DESC LIMIT '+d.eventLimit+''; - s.sqlQuery(eventQuery,eventQueryValues,function(err,r){ + if(monitorRestrictions.length > 0){ + eventWhereQuery = eventWhereQuery.concat([ + monitorRestrictions + ]) + } + console.log(eventWhereQuery) + s.knexQuery({ + action: "select", + columns: "*", + table: "Events", + where: eventWhereQuery, + orderBy: ['time','desc'], + limit: d.eventLimit + },function(err,r) { if(err){ - console.log(eventQuery) - console.error('LINE 2428',err) - setTimeout(function(){ - getEvents(callback) - },2000) + console.error(err) + callback([]) }else{ if(!r){r=[]} r.forEach(function(v,n){ @@ -659,7 +580,6 @@ module.exports = function(s,config,lang,io){ } if(!d.videoLimit&&d.limit){ d.videoLimit=d.limit - eventQuery.push() } if(!d.videoStartDate&&d.startDate){ d.videoStartDate = s.stringToSqlTime(d.startDate) @@ -668,9 +588,10 @@ module.exports = function(s,config,lang,io){ d.videoEndDate = s.stringToSqlTime(d.endDate) } var getVideos = function(callback){ - var videoQuery='SELECT * FROM Videos WHERE ke=?'; - var videoQueryValues=[cn.ke]; - if(d.videoStartDate||d.videoEndDate){ + var videoWhereQuery = [ + ['ke','=',cn.ke], + ] + if(d.videoStartDate || d.videoEndDate){ if(!d.videoStartDateOperator||d.videoStartDateOperator==''){ d.videoStartDateOperator='>=' } @@ -678,38 +599,35 @@ module.exports = function(s,config,lang,io){ d.videoEndDateOperator='<=' } switch(true){ - case(d.videoStartDate&&d.videoStartDate!==''&&d.videoEndDate&&d.videoEndDate!==''): - videoQuery+=' AND `time` '+d.videoStartDateOperator+' ? AND `end` '+d.videoEndDateOperator+' ?'; - videoQueryValues.push(d.videoStartDate) - videoQueryValues.push(d.videoEndDate) + case(d.videoStartDate && d.videoStartDate !== '' && d.videoEndDate && d.videoEndDate !== ''): + videoWhereQuery.push(['time',d.videoStartDateOperator,d.videoStartDate]) + videoWhereQuery.push(['end',d.videoEndDateOperator,d.videoEndDate]) break; - case(d.videoStartDate&&d.videoStartDate!==''): - videoQuery+=' AND `time` '+d.videoStartDateOperator+' ?'; - videoQueryValues.push(d.videoStartDate) + case(d.videoStartDate && d.videoStartDate !== ''): + videoWhereQuery.push(['time',d.videoStartDateOperator,d.videoStartDate]) break; - case(d.videoEndDate&&d.videoEndDate!==''): - videoQuery+=' AND `end` '+d.videoEndDateOperator+' ?'; - videoQueryValues.push(d.videoEndDate) + case(d.videoEndDate && d.videoEndDate !== ''): + videoWhereQuery.push(['end',d.videoEndDateOperator,d.videoEndDate]) break; } } - if(monitorValues.length>0){ - videoQuery += monitorQuery; - videoQueryValues = videoQueryValues.concat(monitorValues); + if(monitorRestrictions.length > 0){ + videoWhereQuery = videoWhereQuery.concat([ + monitorRestrictions + ]) } - videoQuery+=' ORDER BY `time` DESC'; - if(!d.videoLimit||d.videoLimit==''){ - d.videoLimit='100' - } - if(d.videoLimit!=='0'){ - videoQuery+=' LIMIT '+d.videoLimit - } - s.sqlQuery(videoQuery,videoQueryValues,function(err,r){ + s.knexQuery({ + action: "select", + columns: "*", + table: "Videos", + where: videoWhereQuery, + orderBy: ['time','desc'], + limit: d.videoLimit || '100' + },function(err,r) { if(err){ - console.log(videoQuery) - console.error('LINE 2416',err) + console.error(err) setTimeout(function(){ - getVideos(callback) + callback({total:0,limit:d.videoLimit,videos:[]}) },2000) }else{ s.buildVideoLinks(r,{ @@ -777,7 +695,16 @@ module.exports = function(s,config,lang,io){ tx({f:'monitor_watch_off',ke:d.ke,id:d.id,cnid:cn.id}) break; case'start':case'stop': - s.sqlQuery('SELECT * FROM Monitors WHERE ke=? AND mid=?',[cn.ke,d.id],function(err,r) { + s.knexQuery({ + action: "select", + columns: "*", + table: "Monitors", + where: [ + ['ke','=',cn.ke], + ['mid','=',d.id], + ], + limit: 1 + },function(err,r) { if(r && r[0]){ r = r[0] s.camera(d.ff,{type:r.type,url:s.buildMonitorUrl(r),id:d.id,mode:d.ff,ke:cn.ke}); @@ -820,15 +747,19 @@ module.exports = function(s,config,lang,io){ case'logs': switch(d.ff){ case'delete': - //config.webPaths.superApiPrefix+':auth/logs/delete' - s.sqlQuery('DELETE FROM Logs WHERE ke=?',[d.ke]) + s.knexQuery({ + action: "delete", + table: "Logs", + where: [ + ['ke','=',d.ke], + ] + }) break; } break; case'system': switch(d.ff){ case'update': - //config.webPaths.superApiPrefix+':auth/update' s.ffmpegKill() s.systemLog('Shinobi ordered to update',{ by:cn.mail, @@ -867,145 +798,25 @@ module.exports = function(s,config,lang,io){ break; } break; - case'accounts': - switch(d.ff){ - case'saveSuper': - var currentSuperUserList = jsonfile.readFileSync(s.location.super) - var currentSuperUser = {} - var currentSuperUserPosition = -1 - //find this user in current list - currentSuperUserList.forEach(function(user,pos){ - if(user.mail === cn.mail){ - currentSuperUser = user - currentSuperUserPosition = pos - } - }) - var logDetails = { - by : cn.mail, - ip : cn.ip - } - //check if pass and pass_again match, if not remove password - if(d.form.pass !== '' && d.form.pass === d.form.pass_again){ - d.form.pass = s.createHash(d.form.pass) - }else{ - delete(d.form.pass) - } - //delete pass_again from object - delete(d.form.pass_again) - //set new values - currentSuperUser = Object.assign(currentSuperUser,d.form) - //reset email and log change of email - if(d.form.mail !== cn.mail){ - logDetails.newEmail = d.form.mail - logDetails.oldEmail = cn.mail + '' - cn.mail = d.form.mail - } - //log this change - s.systemLog('super.json Modified',logDetails) - //modify or add account in temporary master list - if(currentSuperUserList[currentSuperUserPosition]){ - currentSuperUserList[currentSuperUserPosition] = currentSuperUser - }else{ - currentSuperUserList.push(currentSuperUser) - } - //update master list in system - jsonfile.writeFile(s.location.super,currentSuperUserList,{spaces: 2},function(){ - s.tx({f:'save_preferences'},cn.id) - }) - break; - case'register': - if(d.form.mail!==''&&d.form.pass!==''){ - if(d.form.pass===d.form.password_again){ - s.sqlQuery('SELECT * FROM Users WHERE mail=?',[d.form.mail],function(err,r) { - if(r&&r[0]){ - //found address already exists - d.msg=lang['Email address is in use.']; - s.tx({f:'error',ff:'account_register',msg:d.msg},cn.id) - }else{ - //create new - //user id - d.form.uid=s.gid(); - //check to see if custom key set - if(!d.form.ke||d.form.ke===''){ - d.form.ke=s.gid() - }else{ - d.form.ke = d.form.ke.replace(/[`~!@#$%^&*()_|+\-=?;:'",.<>\{\}\[\]\\\/]/gi, '') - } - //write user to db - s.sqlQuery('INSERT INTO Users (ke,uid,mail,pass,details) VALUES (?,?,?,?,?)',[d.form.ke,d.form.uid,d.form.mail,s.createHash(d.form.pass),d.form.details]) - s.tx({f:'add_account',details:d.form.details,ke:d.form.ke,uid:d.form.uid,mail:d.form.mail},'$'); - //init user - s.loadGroup(d.form) - } - }) - }else{ - d.msg=lang["Passwords Don't Match"]; - } - }else{ - d.msg=lang['Fields cannot be empty']; - } - if(d.msg){ - s.tx({f:'error',ff:'account_register',msg:d.msg},cn.id) - } - break; - case'edit': - s.sqlQuery('SELECT * FROM Users WHERE mail=?',[d.account.mail],function(err,r) { - if(r && r[0]){ - r = r[0] - var details = JSON.parse(r.details) - if(d.form.pass&&d.form.pass!==''){ - if(d.form.pass===d.form.password_again){ - d.form.pass=s.createHash(d.form.pass); - }else{ - s.tx({f:'error',ff:'edit_account',msg:lang["Passwords Don't Match"]},cn.id) - return - } - }else{ - delete(d.form.pass); - } - delete(d.form.password_again); - d.keys=Object.keys(d.form); - d.set=[]; - d.values=[]; - d.keys.forEach(function(v,n){ - if(d.set==='ke'||d.set==='password_again'||!d.form[v]){return} - d.set.push(v+'=?') - if(v === 'details'){ - d.form[v] = JSON.stringify(Object.assign(details,JSON.parse(d.form[v]))) - } - d.values.push(d.form[v]) - }) - d.values.push(d.account.mail) - s.sqlQuery('UPDATE Users SET '+d.set.join(',')+' WHERE mail=?',d.values,function(err,r) { - if(err){ - console.log(err) - s.tx({f:'error',ff:'edit_account',msg:lang.AccountEditText1},cn.id) - return - } - s.tx({f:'edit_account',form:d.form,ke:d.account.ke,uid:d.account.uid},'$'); - delete(s.group[d.account.ke].init); - s.loadGroupApps(d.account) - }) - } - }) - break; - case'delete': - s.sqlQuery('DELETE FROM Users WHERE uid=? AND ke=? AND mail=?',[d.account.uid,d.account.ke,d.account.mail]) - s.sqlQuery('DELETE FROM API WHERE uid=? AND ke=?',[d.account.uid,d.account.ke]) - s.tx({f:'delete_account',ke:d.account.ke,uid:d.account.uid,mail:d.account.mail},'$'); - break; - } - break; } } } }) // admin page socket functions cn.on('a',function(d){ - if(!cn.init&&d.f=='init'){ - s.sqlQuery('SELECT * FROM Users WHERE auth=? AND uid=?',[d.auth,d.uid],function(err,r){ - if(r&&r[0]){ - r=r[0]; + if(!cn.init && d.f == 'init'){ + s.knexQuery({ + action: "select", + columns: "*", + table: "Users", + where: [ + ['auth','=',d.auth], + ['uid','=',d.uid], + ], + limit: 1 + },function(err,r) { + if(r && r[0]){ + r = r[0]; if(!s.group[d.ke]){s.group[d.ke]={users:{}}} if(!s.group[d.ke].users[d.auth]){s.group[d.ke].users[d.auth]={cnid:cn.id,uid:d.uid,ke:d.ke,auth:d.auth}} try{s.group[d.ke].users[d.auth].details=JSON.parse(r.details)}catch(er){} @@ -1015,59 +826,29 @@ module.exports = function(s,config,lang,io){ cn.auth=d.auth; cn.init='admin'; }else{ - cn.disconnect(); + cn.disconnect() } }) }else{ - s.auth({auth:d.auth,ke:d.ke,id:d.id,ip:cn.request.connection.remoteAddress},function(user){ - if(!user.details.sub){ - switch(d.f){ - case'accounts': - switch(d.ff){ - case'edit': - d.keys=Object.keys(d.form); - d.condition=[]; - d.value=[]; - d.keys.forEach(function(v){ - d.condition.push(v+'=?') - d.value.push(d.form[v]) - }) - d.value=d.value.concat([d.ke,d.$uid]) - s.sqlQuery("UPDATE Users SET "+d.condition.join(',')+" WHERE ke=? AND uid=?",d.value) - s.tx({f:'edit_sub_account',ke:d.ke,uid:d.$uid,mail:d.mail,form:d.form},'ADM_'+d.ke); - s.sqlQuery("SELECT * FROM API WHERE ke=? AND uid=?",[d.ke,d.$uid],function(err,rows){ - if(rows && rows[0]){ - rows.forEach(function(row){ - delete(s.api[row.code]) - }) - } - }) - break; - case'delete': - s.sqlQuery('DELETE FROM Users WHERE uid=? AND ke=? AND mail=?',[d.$uid,d.ke,d.mail]) - s.sqlQuery("SELECT * FROM API WHERE ke=? AND uid=?",[d.ke,d.$uid],function(err,rows){ - if(rows && rows[0]){ - rows.forEach(function(row){ - delete(s.api[row.code]) - }) - s.sqlQuery('DELETE FROM API WHERE uid=? AND ke=?',[d.$uid,d.ke]) - } - }) - s.tx({f:'delete_sub_account',ke:d.ke,uid:d.$uid,mail:d.mail},'ADM_'+d.ke); - break; - } - break; - } - } - }) + cn.disconnect() } }) //functions for webcam recorder cn.on('r',function(d){ if(!cn.ke&&d.f==='init'){ - s.sqlQuery('SELECT ke,uid,auth,mail,details FROM Users WHERE ke=? AND auth=? AND uid=?',[d.ke,d.auth,d.uid],function(err,r) { - if(r&&r[0]){ - r=r[0] + s.knexQuery({ + action: "select", + columns: "ke,uid,auth,mail,details", + table: "Users", + where: [ + ['ke','=',d.ke], + ['auth','=',d.auth], + ['uid','=',d.uid], + ], + limit: 1 + },function(err,r) { + if(r && r[0]){ + r = r[0] cn.ke=d.ke,cn.uid=d.uid,cn.auth=d.auth; if(!s.group[d.ke])s.group[d.ke]={}; if(!s.group[d.ke].users)s.group[d.ke].users={}; @@ -1104,6 +885,9 @@ module.exports = function(s,config,lang,io){ if(s.group[d.ke] && s.group[d.ke].activeMonitors[d.mid]){ if(s.group[d.ke].activeMonitors[d.mid].allowStdinWrite === true){ switch(d.f){ + case'monitor_b64': + console.log(d) + break; case'monitor_chunk': if(s.group[d.ke].activeMonitors[d.mid].isStarted !== true || !s.group[d.ke].activeMonitors[d.mid].spawn || !s.group[d.ke].activeMonitors[d.mid].spawn.stdin){ s.tx({error:'Not Started'},cn.id); From 6dfdfe2aa04a541a1d093cc7e49329b743ea29f9 Mon Sep 17 00:00:00 2001 From: Moe Date: Thu, 9 Jul 2020 22:48:54 -0700 Subject: [PATCH 012/175] sqlQuery Conversion : Add grouped where conditions --- libs/sql.js | 66 ++++++++++++++++++++++++++++++++++++----------------- 1 file changed, 45 insertions(+), 21 deletions(-) diff --git a/libs/sql.js b/libs/sql.js index eab21521..6b85b05f 100644 --- a/libs/sql.js +++ b/libs/sql.js @@ -61,8 +61,39 @@ module.exports = function(s,config){ .raw(data.query,data.values) .asCallback(callback) }, 4); + const processWhereCondition = (dbQuery,where,didOne) => { + var whereIsArray = where instanceof Array; + if(where[0] && where[0] instanceof Array){ + dbQuery.where(function() { + var _this = this + var didOneInsideGroup = false + where.forEach((whereInsideGroup) => { + console.log('LINE',whereInsideGroup) + processWhereCondition(_this,whereInsideGroup,didOneInsideGroup) + }) + }) + }else if(!didOne){ + didOne = true + whereIsArray ? dbQuery.where(...where) : dbQuery.where(where) + }else if(where.length === 4){ + const separator = where[0] + '' + where.shift() + switch(separator){ + case'and': + whereIsArray ? dbQuery.andWhere(...where) : dbQuery.andWhere(where) + break; + case'or': + whereIsArray ? dbQuery.orWhere(...where) : dbQuery.orWhere(where) + break; + } + }else{ + whereIsArray ? dbQuery.andWhere(...where) : dbQuery.andWhere(where) + } + + } const knexQuery = (options,callback) => { - if(config.debugLog === true){ + if(!s.databaseEngine)return// console.log('Database Not Set'); + if(config.debugLogVerbose && config.debugLog === true){ s.debugLog('s.knexQuery QUERY',options) } // options = { @@ -73,7 +104,7 @@ module.exports = function(s,config){ var dbQuery switch(options.action){ case'select': - !options.columns ? '*' : options.columns.indexOf(',') > -1 ? options.columns.split(',') : options.columns; + options.columns = options.columns.indexOf(',') === -1 ? [options.columns] : options.columns.split(','); dbQuery = s.databaseEngine.select(...options.columns).from(options.table) break; case'update': @@ -89,24 +120,7 @@ module.exports = function(s,config){ if(options.where){ var didOne = false; options.where.forEach((where) => { - var whereIsArray = where instanceof Array; - if(!didOne){ - didOne = true - whereIsArray ? dbQuery.where(...where) : dbQuery.where(where) - }else if(where.length === 4){ - const separator = where[0] + '' - where.shift() - switch(separator){ - case'and': - whereIsArray ? dbQuery.andWhere(...where) : dbQuery.andWhere(where) - break; - case'or': - whereIsArray ? dbQuery.orWhere(...where) : dbQuery.orWhere(where) - break; - } - }else{ - whereIsArray ? dbQuery.andWhere(...where) : dbQuery.andWhere(where) - } + processWhereCondition(dbQuery,where,didOne) }) } if(options.orderBy){ @@ -115,6 +129,9 @@ module.exports = function(s,config){ if(options.limit){ dbQuery.limit(options.limit) } + if(config.debugLog === true){ + console.log(dbQuery.toString()) + } if(callback || options.update || options.insert){ dbQuery.asCallback(function(err,r) { if(err)console.log(err) @@ -292,7 +309,14 @@ module.exports = function(s,config){ var endTimeOperator = options.endTimeOperator var startTime = options.startTime if(preliminaryValidationFailed){ - callback([]); + if(options.noFormat){ + callback([]); + }else{ + callback({ + ok: true, + [rowName]: [], + }) + } return } var queryString = 'SELECT * FROM `' + theTableSelected + '` WHERE ke=?' From 7f42e3efd0e8252d4aaa668b3ca42db79d00687b Mon Sep 17 00:00:00 2001 From: Moe Date: Fri, 10 Jul 2020 17:30:08 -0700 Subject: [PATCH 013/175] sqlQuery Conversion : timelapse.js (also refactored backend slightly) --- libs/monitor.js | 29 +++++ libs/timelapse.js | 284 ++++++++++++++++++++++++---------------------- 2 files changed, 179 insertions(+), 134 deletions(-) diff --git a/libs/monitor.js b/libs/monitor.js index abb2b6c5..1892e32c 100644 --- a/libs/monitor.js +++ b/libs/monitor.js @@ -1734,6 +1734,35 @@ module.exports = function(s,config,lang){ }) return cameras } + s.getMonitorRestrictions = (permissions,monitorId) => { + const monitorRestrictions = [] + if( + !monitorId && + permissions.sub && + permissions.monitors && + permissions.allmonitors !== '1' + ){ + try{ + permissions.monitors = JSON.parse(permissions.monitors) + permissions.monitors.forEach(function(v,n){ + if(n === 0){ + monitorRestrictions.push(['mid','=',v]) + }else{ + monitorRestrictions.push(['or','mid','=',v]) + } + }) + }catch(er){ + console.log(er) + } + }else if( + !permissions.sub || + permissions.allmonitors !== '0' || + permissions.monitors.indexOf(monitorId) >- 1 + ){ + monitorRestrictions.push(['mid','=',monitorId]) + } + return monitorRestrictions + } // s.checkViewerConnectionsForMonitor = function(monitorObject){ // var monitorConfig = s.group[monitorObject.ke].rawMonitorConfigurations[monitorObject.mid] // if(monitorConfig.mode === 'start'){ diff --git a/libs/timelapse.js b/libs/timelapse.js index d8b0efc5..a6f95230 100644 --- a/libs/timelapse.js +++ b/libs/timelapse.js @@ -2,6 +2,78 @@ var fs = require('fs') var moment = require('moment') var express = require('express') module.exports = function(s,config,lang,app,io){ + var getFrameRows = function(options,callback){ + var whereQuery = [ + ['ke','=',options.groupKey], + ] + const monitorRestrictions = options.monitorRestrictions + var frameLimit = parseInt(options.limit) || 500 + const chosenDate = options.date + const startDate = options.startDate ? s.stringToSqlTime(options.startDate) : null + const endDate = options.endDate ? s.stringToSqlTime(options.endDate) : null + const startOperator = options.startOperator || '>=' + const endOperator = options.endOperator || '<=' + if(chosenDate){ + if(chosenDate.indexOf('-') === -1 && !isNaN(chosenDate)){ + chosenDate = parseInt(chosenDate) + } + var selectedDate = chosenDate + if(typeof chosenDate === 'string' && chosenDate.indexOf('.') > -1){ + selectedDate = chosenDate.split('.')[0] + } + selectedDate = new Date(selectedDate) + var utcSelectedDate = new Date(selectedDate.getTime() + selectedDate.getTimezoneOffset() * 60000) + startDate = moment(utcSelectedDate).format('YYYY-MM-DD HH:mm:ss') + var dayAfter = utcSelectedDate + dayAfter.setDate(dayAfter.getDate() + 1) + endDate = moment(dayAfter).format('YYYY-MM-DD HH:mm:ss') + } + if(startDate){ + if(endDate){ + whereQuery.push(['time',startOperator,startDate]) + whereQuery.push(['time',endOperator,endDate]) + }else{ + whereQuery.push(['time',startOperator,startDate]) + } + } + if(monitorRestrictions && monitorRestrictions.length > 0){ + whereQuery.push(monitorRestrictions) + } + if(options.archived){ + whereQuery.push(['details','LIKE',`%"archived":"1"%`]) + } + if(options.filename){ + whereQuery.push(['filename','=',options.filename]) + frameLimit = "1"; + } + s.knexQuery({ + action: "select", + columns: "*", + table: "Timelapse Frames", + where: whereQuery, + orderBy: ['time','desc'], + limit: frameLimit || '500' + },function(err,r) { + if(err){ + callback({ + ok: false, + total: 0, + limit: frameLimit, + frames: [] + }) + }else{ + r.forEach(function(file){ + file.details = s.parseJSON(file.details) + }) + callback({ + ok: true, + total: r.length, + limit: frameLimit, + frames: r + }) + } + }) + } s.getTimelapseFrameDirectory = function(e){ if(e.mid&&!e.id){e.id=e.mid} s.checkDetails(e) @@ -74,7 +146,11 @@ module.exports = function(s,config,lang,app,io){ } } s.insertTimelapseFrameDatabaseRow = function(e,queryInfo,filePath){ - s.sqlQuery('INSERT INTO `Timelapse Frames` ('+Object.keys(queryInfo).join(',')+') VALUES (?,?,?,?,?,?)',Object.values(queryInfo)) + s.knexQuery({ + action: "insert", + table: "Timelapse Frames", + insert: queryInfo + }) s.setDiskUsedForGroup(e,queryInfo.size / 1048576,'timelapeFrames') s.purgeDiskForGroup(e) s.onInsertTimelapseFrameExtensions.forEach(function(extender){ @@ -103,11 +179,24 @@ module.exports = function(s,config,lang,app,io){ s.deleteTimelapseFrameFromCloud = function(e){ // e = video object s.checkDetails(e) - var frameSelector = [e.id,e.ke,new Date(e.time)] - s.sqlQuery('SELECT * FROM `Cloud Timelapse Frames` WHERE `mid`=? AND `ke`=? AND `time`=?',frameSelector,function(err,r){ - if(r&&r[0]){ + var frameSelector = [ + ['ke','=',e.ke], + ['mid','=',e.id], + ['time','=',new Date(e.time)], + ] + s.knexQuery({ + action: "select", + columns: "*", + table: "Cloud Timelapse Frames", + where: frameSelector + },function(err,r){ + if(r && r[0]){ r = r[0] - s.sqlQuery('DELETE FROM `Cloud Timelapse Frames` WHERE `mid`=? AND `ke`=? AND `time`=?',frameSelector,function(){ + s.knexQuery({ + action: "delete", + table: "Cloud Timelapse Frames", + where: frameSelector + },function(){ s.onDeleteTimelapseFrameFromCloudExtensionsRunner(e,r) }) }else{ @@ -131,112 +220,51 @@ module.exports = function(s,config,lang,app,io){ var hasRestrictions = user.details.sub && user.details.allmonitors !== '1' if( user.permissions.watch_videos==="0" || - hasRestrictions && (!user.details.video_view || user.details.video_view.indexOf(req.params.id)===-1) + hasRestrictions && + ( + !user.details.video_view || + user.details.video_view.indexOf(req.params.id) === -1 + ) ){ - res.end(s.prettyPrint([])) + s.closeJsonResponse(res,[]) return } - req.sql='SELECT * FROM `Timelapse Frames` WHERE ke=?';req.ar=[req.params.ke]; - if(req.query.archived=='1'){ - req.sql+=' AND details LIKE \'%"archived":"1"\'' - } - if(!req.params.id){ - if(user.details.sub&&user.details.monitors&&user.details.allmonitors!=='1'){ - try{user.details.monitors=JSON.parse(user.details.monitors);}catch(er){} - req.or=[]; - user.details.monitors.forEach(function(v,n){ - req.or.push('mid=?');req.ar.push(v) - }) - req.sql+=' AND ('+req.or.join(' OR ')+')' - } - }else{ - if(!user.details.sub||user.details.allmonitors!=='0'||user.details.monitors.indexOf(req.params.id)>-1){ - req.sql+=' and mid=?' - req.ar.push(req.params.id) - }else{ - res.end('[]'); - return; - } - } - var isMp4Call = false - if(req.query.mp4){ - isMp4Call = true - } - if(req.params.date){ - if(req.params.date.indexOf('-') === -1 && !isNaN(req.params.date)){ - req.params.date = parseInt(req.params.date) - } - var selectedDate = req.params.date - if(typeof req.params.date === 'string' && req.params.date.indexOf('.') > -1){ - isMp4Call = true - selectedDate = req.params.date.split('.')[0] - } - selectedDate = new Date(selectedDate) - var utcSelectedDate = new Date(selectedDate.getTime() + selectedDate.getTimezoneOffset() * 60000) - req.query.start = moment(utcSelectedDate).format('YYYY-MM-DD HH:mm:ss') - var dayAfter = utcSelectedDate - dayAfter.setDate(dayAfter.getDate() + 1) - req.query.end = moment(dayAfter).format('YYYY-MM-DD HH:mm:ss') - } - if(req.query.start||req.query.end){ - if(!req.query.startOperator||req.query.startOperator==''){ - req.query.startOperator='>=' - } - if(!req.query.endOperator||req.query.endOperator==''){ - req.query.endOperator='<=' - } - if(req.query.start && req.query.start !== '' && req.query.end && req.query.end !== ''){ - req.query.start = s.stringToSqlTime(req.query.start) - req.query.end = s.stringToSqlTime(req.query.end) - req.sql+=' AND `time` '+req.query.startOperator+' ? AND `time` '+req.query.endOperator+' ?'; - req.ar.push(req.query.start) - req.ar.push(req.query.end) - }else if(req.query.start && req.query.start !== ''){ - req.query.start = s.stringToSqlTime(req.query.start) - req.sql+=' AND `time` '+req.query.startOperator+' ?'; - req.ar.push(req.query.start) - } - } - // if(!req.query.limit||req.query.limit==''){req.query.limit=288} - req.sql+=' ORDER BY `time` DESC' - s.sqlQuery(req.sql,req.ar,function(err,r){ - if(isMp4Call){ - if(r && r[0]){ - s.createVideoFromTimelapse(r,req.query.fps,function(response){ - if(response.fileExists){ - if(req.query.download){ - res.setHeader('Content-Type', 'video/mp4') - s.streamMp4FileOverHttp(response.fileLocation,req,res) - }else{ - res.setHeader('Content-Type', 'application/json') - res.end(s.prettyPrint({ - ok : response.ok, - fileExists : response.fileExists, - msg : response.msg, - })) - } + const monitorRestrictions = s.getMonitorRestrictions(user.details,req.params.id) + getFrameRows({ + monitorRestrictions: monitorRestrictions, + groupKey: req.params.ke, + date: req.query.date, + startDate: req.query.startDate, + endDate: req.query.endDate, + startOperator: req.query.startOperator, + endOperator: req.query.endOperator, + limit: req.query.limit, + archived: req.query.archived, + },(response) => { + var isMp4Call = !!(req.query.mp4 || (req.params.date && typeof req.params.date === 'string' && req.params.date.indexOf('.') > -1)) + if(isMp4Call && response.frames[0]){ + s.createVideoFromTimelapse(response.frames,req.query.fps,function(response){ + if(response.fileExists){ + if(req.query.download){ + res.setHeader('Content-Type', 'video/mp4') + s.streamMp4FileOverHttp(response.fileLocation,req,res) }else{ - res.setHeader('Content-Type', 'application/json') - res.end(s.prettyPrint({ + s.closeJsonResponse(res,{ ok : response.ok, fileExists : response.fileExists, msg : response.msg, - })) + }) } - }) - }else{ - res.setHeader('Content-Type', 'application/json'); - res.end(s.prettyPrint([])) - } + }else{ + s.closeJsonResponse(res,{ + ok : response.ok, + fileExists : response.fileExists, + msg : response.msg, + }) + } + }) }else{ - if(r && r[0]){ - r.forEach(function(file){ - file.details = s.parseJSON(file.details) - }) - res.end(s.prettyPrint(r)) - }else{ - res.end(s.prettyPrint([])) - } + s.closeJsonResponse(res,response.frames) } }) },res,req); @@ -257,35 +285,15 @@ module.exports = function(s,config,lang,app,io){ res.end(s.prettyPrint([])) return } - req.sql='SELECT * FROM `Timelapse Frames` WHERE ke=?';req.ar=[req.params.ke]; - if(req.query.archived=='1'){ - req.sql+=' AND details LIKE \'%"archived":"1"\'' - } - if(!req.params.id){ - if(user.details.sub&&user.details.monitors&&user.details.allmonitors!=='1'){ - try{user.details.monitors=JSON.parse(user.details.monitors);}catch(er){} - req.or=[]; - user.details.monitors.forEach(function(v,n){ - req.or.push('mid=?');req.ar.push(v) - }) - req.sql+=' AND ('+req.or.join(' OR ')+')' - } - }else{ - if(!user.details.sub||user.details.allmonitors!=='0'||user.details.monitors.indexOf(req.params.id)>-1){ - req.sql+=' and mid=?' - req.ar.push(req.params.id) - }else{ - res.end('[]'); - return; - } - } - req.sql+=' AND filename=?' - req.ar.push(req.params.filename) - req.sql+=' ORDER BY `time` DESC' - s.sqlQuery(req.sql,req.ar,function(err,r){ - if(r && r[0]){ - var frame = r[0] - frame.details = s.parseJSON(frame.details) + const monitorRestrictions = s.getMonitorRestrictions(user.details,req.params.id) + getFrameRows({ + monitorRestrictions: monitorRestrictions, + groupKey: req.params.ke, + archived: req.query.archived, + filename: req.params.filename, + },(response) => { + var frame = response.frames[0] + if(frame){ var fileLocation if(frame.details.dir){ fileLocation = `${s.checkCorrectPathEnding(frame.details.dir)}` @@ -303,11 +311,11 @@ module.exports = function(s,config,lang,app,io){ res.on('finish',function(){res.end()}) fs.createReadStream(fileLocation).pipe(res) }else{ - res.end(s.prettyPrint({ok: false, msg: lang[`Nothing exists`]})) + s.closeJsonResponse(res,{ok: false, msg: lang[`Nothing exists`]}) } }) }else{ - res.end(s.prettyPrint({ok: false, msg: lang[`Nothing exists`]})) + s.closeJsonResponse(res,{ok: false, msg: lang[`Nothing exists`]}) } }) },res,req); @@ -338,7 +346,15 @@ module.exports = function(s,config,lang,app,io){ if(hoursNow === 1){ var dateNowMoment = moment(dateNow).utc().format('YYYY-MM-DDTHH:mm:ss') var dateMinusOneDay = moment(dateNow).utc().subtract(1, 'days').format('YYYY-MM-DDTHH:mm:ss') - s.sqlQuery('SELECT * FROM `Timelapse Frames` WHERE time => ? AND time =< ?',[dateMinusOneDay,dateNowMoment],function(err,frames){ + s.knexQuery({ + action: "select", + columns: "*", + table: "Timelapse Frames", + where: [ + ['time','=>',dateMinusOneDay], + ['time','=<',dateNowMoment], + ] + },function(err,frames) { console.log(frames.length) var groups = {} frames.forEach(function(frame){ From aebd01cefd0b0141f423660f0e45b006885eb941 Mon Sep 17 00:00:00 2001 From: Moe Date: Fri, 10 Jul 2020 17:30:31 -0700 Subject: [PATCH 014/175] sqlQuery Conversion : minor update to socketio.js --- libs/socketio.js | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/libs/socketio.js b/libs/socketio.js index 386a6a68..16cbe2a2 100644 --- a/libs/socketio.js +++ b/libs/socketio.js @@ -553,9 +553,7 @@ module.exports = function(s,config,lang,io){ } } if(monitorRestrictions.length > 0){ - eventWhereQuery = eventWhereQuery.concat([ - monitorRestrictions - ]) + eventWhereQuery.push(monitorRestrictions) } console.log(eventWhereQuery) s.knexQuery({ @@ -612,9 +610,7 @@ module.exports = function(s,config,lang,io){ } } if(monitorRestrictions.length > 0){ - videoWhereQuery = videoWhereQuery.concat([ - monitorRestrictions - ]) + videoWhereQuery.push(monitorRestrictions) } s.knexQuery({ action: "select", From 1abef5ebe7d7a013485f8ca17c7418795e683efc Mon Sep 17 00:00:00 2001 From: Moe Date: Fri, 10 Jul 2020 18:58:23 -0700 Subject: [PATCH 015/175] sqlQuery Conversion : uploaders --- libs/uploaders/amazonS3.js | 64 +++++++++++++++++++---------------- libs/uploaders/backblazeB2.js | 35 ++++++++++--------- libs/uploaders/googleDrive.js | 58 +++++++++++++++++-------------- libs/uploaders/s3based.js | 58 +++++++++++++++++-------------- libs/uploaders/webdav.js | 35 ++++++++++--------- 5 files changed, 137 insertions(+), 113 deletions(-) diff --git a/libs/uploaders/amazonS3.js b/libs/uploaders/amazonS3.js index 58aeef84..5a8d4a0a 100644 --- a/libs/uploaders/amazonS3.js +++ b/libs/uploaders/amazonS3.js @@ -100,23 +100,26 @@ module.exports = function(s,config,lang){ s.userLog(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.knexQuery({ + action: "insert", + table: "Cloud Videos", + insert: { + mid: e.mid, + ke: e.ke, + time: k.startTime, + status: 1, + details: s.s({ + type : 's3', + location : saveLocation + }), + size: k.filesize, + end: k.endTime, + href: data.Location + } + }) s.setCloudDiskUsedForGroup(e,{ - amount : k.filesizeMB, - storageType : 's3' + amount: k.filesizeMB, + storageType: 's3' }) s.purgeCloudDiskForGroup(e,'s3') } @@ -142,18 +145,21 @@ module.exports = function(s,config,lang){ s.userLog(e,{type:lang['Wasabi Hot Cloud Storage Upload Error'],msg:err}) } if(s.group[e.ke].init.aws_s3_log === '1' && data && data.Location){ - var save = [ - queryInfo.mid, - queryInfo.ke, - queryInfo.time, - s.s({ - type : 's3', - location : saveLocation, - }), - queryInfo.size, - data.Location - ] - s.sqlQuery('INSERT INTO `Cloud Timelapse Frames` (mid,ke,time,details,size,href) VALUES (?,?,?,?,?,?)',save) + s.knexQuery({ + action: "insert", + table: "Cloud Timelapse Frames", + insert: { + mid: queryInfo.mid, + ke: queryInfo.ke, + time: queryInfo.time, + details: s.s({ + type : 's3', + location : saveLocation + }), + size: queryInfo.size, + href: data.Location + } + }) s.setCloudDiskUsedForGroup(e,{ amount : s.kilobyteToMegabyte(queryInfo.size), storageType : 's3' @@ -405,4 +411,4 @@ module.exports = function(s,config,lang){ }, ] } -} \ No newline at end of file +} diff --git a/libs/uploaders/backblazeB2.js b/libs/uploaders/backblazeB2.js index ae6f688b..6980db20 100644 --- a/libs/uploaders/backblazeB2.js +++ b/libs/uploaders/backblazeB2.js @@ -129,22 +129,25 @@ module.exports = function(s,config,lang){ }).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.knexQuery({ + action: "insert", + table: "Cloud Videos", + insert: { + mid: e.mid, + ke: e.ke, + time: k.startTime, + status: 1, + details: s.s({ + type : 'b2', + bucketId : resp.data.bucketId, + fileId : resp.data.fileId, + fileName : resp.data.fileName + }), + size: k.filesize, + end: k.endTime, + href: backblazeDownloadUrl + } + }) s.setCloudDiskUsedForGroup(e,{ amount : k.filesizeMB, storageType : 'b2' diff --git a/libs/uploaders/googleDrive.js b/libs/uploaders/googleDrive.js index 1f972fef..5460bc45 100644 --- a/libs/uploaders/googleDrive.js +++ b/libs/uploaders/googleDrive.js @@ -157,20 +157,23 @@ module.exports = (s,config,lang,app,io) => { const data = response.data if(s.group[e.ke].init.googd_log === '1' && data && data.id){ - var save = [ - e.mid, - e.ke, - k.startTime, - 1, - s.s({ - type : 'googd', - id : data.id - }), - k.filesize, - k.endTime, - '' - ] - s.sqlQuery('INSERT INTO `Cloud Videos` (mid,ke,time,status,details,size,end,href) VALUES (?,?,?,?,?,?,?,?)',save) + s.knexQuery({ + action: "insert", + table: "Cloud Videos", + insert: { + mid: e.mid, + ke: e.ke, + time: k.startTime, + status: 1, + details: s.s({ + type: 'googd', + id: data.id + }), + size: k.filesize, + end: k.endTime, + href: '' + } + }) s.setCloudDiskUsedForGroup(e,{ amount : k.filesizeMB, storageType : 'googd' @@ -208,18 +211,21 @@ module.exports = (s,config,lang,app,io) => { s.userLog(e,{type:lang['Google Drive Storage Upload Error'],msg:err}) } if(s.group[e.ke].init.googd_log === '1' && data && data.id){ - var save = [ - queryInfo.mid, - queryInfo.ke, - queryInfo.time, - s.s({ - type : 'googd', - id : data.id, - }), - queryInfo.size, - '' - ] - s.sqlQuery('INSERT INTO `Cloud Timelapse Frames` (mid,ke,time,details,size,href) VALUES (?,?,?,?,?,?)',save) + s.knexQuery({ + action: "insert", + table: "Cloud Timelapse Frames", + insert: { + mid: queryInfo.mid, + ke: queryInfo.ke, + time: queryInfo.time, + details: s.s({ + type : 'googd', + id : data.id, + }), + size: queryInfo.size, + href: '' + } + }) s.setCloudDiskUsedForGroup(e,{ amount : s.kilobyteToMegabyte(queryInfo.size), storageType : 'googd' diff --git a/libs/uploaders/s3based.js b/libs/uploaders/s3based.js index 243530db..945afcfa 100644 --- a/libs/uploaders/s3based.js +++ b/libs/uploaders/s3based.js @@ -117,20 +117,23 @@ module.exports = function(s,config,lang){ if(s.group[e.ke].init.whcs_log === '1' && data && data.Location){ var cloudLink = data.Location cloudLink = fixCloudianUrl(e,cloudLink) - var save = [ - e.mid, - e.ke, - k.startTime, - 1, - s.s({ - type : 'whcs', - location : saveLocation - }), - k.filesize, - k.endTime, - cloudLink - ] - s.sqlQuery('INSERT INTO `Cloud Videos` (mid,ke,time,status,details,size,end,href) VALUES (?,?,?,?,?,?,?,?)',save) + s.knexQuery({ + action: "insert", + table: "Cloud Videos", + insert: { + mid: e.mid, + ke: e.ke, + time: k.startTime, + status: 1, + details: s.s({ + type : 'whcs', + location : saveLocation + }), + size: k.filesize, + end: k.endTime, + href: cloudLink + } + }) s.setCloudDiskUsedForGroup(e,{ amount : k.filesizeMB, storageType : 'whcs' @@ -159,18 +162,21 @@ module.exports = function(s,config,lang){ s.userLog(e,{type:lang['Wasabi Hot Cloud Storage Upload Error'],msg:err}) } if(s.group[e.ke].init.whcs_log === '1' && data && data.Location){ - var save = [ - queryInfo.mid, - queryInfo.ke, - queryInfo.time, - s.s({ - type : 'whcs', - location : saveLocation, - }), - queryInfo.size, - data.Location - ] - s.sqlQuery('INSERT INTO `Cloud Timelapse Frames` (mid,ke,time,details,size,href) VALUES (?,?,?,?,?,?)',save) + s.knexQuery({ + action: "insert", + table: "Cloud Timelapse Frames", + insert: { + mid: queryInfo.mid, + ke: queryInfo.ke, + time: queryInfo.time, + details: s.s({ + type : 'whcs', + location : saveLocation + }), + size: queryInfo.size, + href: data.Location + } + }) s.setCloudDiskUsedForGroup(e,{ amount : s.kilobyteToMegabyte(queryInfo.size), storageType : 'whcs' diff --git a/libs/uploaders/webdav.js b/libs/uploaders/webdav.js index d6840fb9..8eb531c9 100644 --- a/libs/uploaders/webdav.js +++ b/libs/uploaders/webdav.js @@ -81,23 +81,26 @@ module.exports = function(s,config,lang){ 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.knexQuery({ + action: "insert", + table: "Cloud Videos", + insert: { + mid: e.mid, + ke: e.ke, + time: k.startTime, + status: 1, + details: s.s({ + type : 'webdav', + location : webdavUploadDir + k.filename + }), + size: k.filesize, + end: k.endTime, + href: webdavRemoteUrl + } + }) s.setCloudDiskUsedForGroup(e,{ - amount : k.filesizeMB, - storageType : 'webdav' + amount: k.filesizeMB, + storageType: 'webdav' }) s.purgeCloudDiskForGroup(e,'webdav') } From 194593e59ceb42a1c334988223710bb1d32f1c18 Mon Sep 17 00:00:00 2001 From: Moe Date: Sat, 11 Jul 2020 00:07:55 -0700 Subject: [PATCH 016/175] sqlQuery Conversion : user, videoDropInServer --- libs/user.js | 428 +++++++++++++++++++++++++++----------- libs/videoDropInServer.js | 13 +- 2 files changed, 322 insertions(+), 119 deletions(-) diff --git a/libs/user.js b/libs/user.js index a2bd3786..7bf76b8b 100644 --- a/libs/user.js +++ b/libs/user.js @@ -24,15 +24,28 @@ module.exports = function(s,config,lang){ var currentPurge = s.group[e.ke].sizePurgeQueue[0] var reRunCheck = function(){} var deleteSetOfVideos = function(err,videos,storageIndex,callback){ - var videosToDelete = [] - var queryValues = [e.ke] var completedCheck = 0 + var whereQuery = [ + ['ke','=',e.ke], + [] + ] if(videos){ + var didOne = false 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) + if(didOne){ + const whereGroup = [ + ['or','mid','=',video.mid], + ['time','=',video.time] + ] + }else{ + didOne = false + const whereGroup = [ + ['mid','=',video.mid], + ['time','=',video.time] + ] + } + whereQuery[1].push(whereGroup) fs.chmod(video.dir,0o777,function(err){ fs.unlink(video.dir,function(err){ ++completedCheck @@ -43,9 +56,12 @@ module.exports = function(s,config,lang){ } }) } - if(videosToDelete.length === completedCheck){ - videosToDelete = videosToDelete.join(' OR ') - s.sqlQuery('DELETE FROM Videos WHERE ke =? AND ('+videosToDelete+')',queryValues,function(){ + if(whereQuery[1].length > 0 && whereQuery[1].length === completedCheck){ + s.knexQuery({ + action: "delete", + table: "Videos", + where: whereQuery + },() => { reRunCheck() }) } @@ -72,22 +88,35 @@ module.exports = function(s,config,lang){ }else{ console.log(err) } - if(videosToDelete.length === 0){ + if(whereQuery[1].length === 0){ if(callback)callback() } } var deleteSetOfTimelapseFrames = function(err,frames,storageIndex,callback){ - var framesToDelete = [] - var queryValues = [e.ke] + var whereQuery = [ + ['ke','=',e.ke], + [] + ] var completedCheck = 0 if(frames){ + var didOne = false frames.forEach(function(frame){ var selectedDate = frame.filename.split('T')[0] var dir = s.getTimelapseFrameDirectory(frame) var fileLocationMid = `${dir}` + frame.filename - framesToDelete.push('(mid=? AND `time`=?)') - queryValues.push(frame.mid) - queryValues.push(frame.time) + if(didOne){ + const whereGroup = [ + ['or','mid','=',frame.mid], + ['time','=',frame.time] + ] + }else{ + didOne = false + const whereGroup = [ + ['mid','=',frame.mid], + ['time','=',frame.time] + ] + } + whereQuery[1].push(whereGroup) fs.unlink(fileLocationMid,function(err){ ++completedCheck if(err){ @@ -97,9 +126,12 @@ module.exports = function(s,config,lang){ } }) } - if(framesToDelete.length === completedCheck){ - framesToDelete = framesToDelete.join(' OR ') - s.sqlQuery('DELETE FROM `Timelapse Frames` WHERE ke =? AND ('+framesToDelete+')',queryValues,function(){ + if(whereQuery[1].length > 0 && whereQuery[1].length === completedCheck){ + s.knexQuery({ + action: "delete", + table: "Timelapse Frames", + where: whereQuery + },() => { reRunCheck() }) } @@ -125,21 +157,33 @@ module.exports = function(s,config,lang){ }else{ console.log(err) } - if(framesToDelete.length === 0){ + if(whereQuery[1].length === 0){ if(callback)callback() } } var deleteSetOfFileBinFiles = function(err,files,storageIndex,callback){ - var filesToDelete = [] - var queryValues = [e.ke] + var whereQuery = [ + ['ke','=',e.ke], + [] + ] var completedCheck = 0 if(files){ files.forEach(function(file){ var dir = s.getFileBinDirectory(file) var fileLocationMid = `${dir}` + file.name - filesToDelete.push('(mid=? AND `name`=?)') - queryValues.push(file.mid) - queryValues.push(file.name) + if(didOne){ + const whereGroup = [ + ['or','mid','=',file.mid], + ['name','=',file.name] + ] + }else{ + didOne = false + const whereGroup = [ + ['mid','=',file.mid], + ['name','=',file.name] + ] + } + whereQuery[1].push(whereGroup) fs.unlink(fileLocationMid,function(err){ ++completedCheck if(err){ @@ -149,9 +193,12 @@ module.exports = function(s,config,lang){ } }) } - if(filesToDelete.length === completedCheck){ - filesToDelete = filesToDelete.join(' OR ') - s.sqlQuery('DELETE FROM `Files` WHERE ke =? AND ('+filesToDelete+')',queryValues,function(){ + if(whereQuery[1].length > 0 && whereQuery[1].length === completedCheck){ + s.knexQuery({ + action: "delete", + table: "Files", + where: whereQuery + },() => { reRunCheck() }) } @@ -168,7 +215,7 @@ module.exports = function(s,config,lang){ }else{ console.log(err) } - if(framesToDelete.length === 0){ + if(whereQuery[1].length === 0){ if(callback)callback() } } @@ -178,9 +225,21 @@ module.exports = function(s,config,lang){ } //run purge command if(s.group[e.ke].usedSpaceVideos > (s.group[e.ke].sizeLimit * (s.group[e.ke].sizeLimitVideoPercent / 100) * config.cron.deleteOverMaxOffset)){ - s.sqlQuery('SELECT * FROM Videos WHERE status != 0 AND details NOT LIKE \'%"archived":"1"%\' AND ke=? AND details NOT LIKE \'%"dir"%\' ORDER BY `time` ASC LIMIT 3',[e.ke],function(err,rows){ - deleteSetOfVideos(err,rows,null,callback) - }) + s.knexQuery({ + action: "select", + columns: "*", + table: "Videos", + where: [ + ['ke','=',e.ke], + ['status','!=','0'], + ['details','NOT LIKE',`%"archived":"1"%`], + ['details','NOT LIKE',`%"dir"%`], + ], + orderBy: ['time','asc'], + limit: 3 + },(err,rows) => { + deleteSetOfVideos(err,rows,null,callback) + }) }else{ callback() } @@ -208,7 +267,19 @@ module.exports = function(s,config,lang){ var storageIndex = s.group[e.ke].addStorageUse[storageId] //run purge command if(storageIndex.usedSpace > (storageIndex.sizeLimit * (storageIndex.deleteOffset || config.cron.deleteOverMaxOffset))){ - s.sqlQuery('SELECT * FROM Videos WHERE status != 0 AND details NOT LIKE \'%"archived":"1"%\' AND ke=? AND details LIKE ? ORDER BY `time` ASC LIMIT 3',[e.ke,`%"dir":"${storage.value}"%`],function(err,rows){ + s.knexQuery({ + action: "select", + columns: "*", + table: "Videos", + where: [ + ['ke','=',e.ke], + ['status','!=','0'], + ['details','NOT LIKE',`%"archived":"1"%`], + ['details','LIKE',`%"dir":"${storage.value}"%`], + ], + orderBy: ['time','asc'], + limit: 3 + },(err,rows) => { deleteSetOfVideos(err,rows,storageIndex,callback) }) }else{ @@ -225,9 +296,19 @@ module.exports = function(s,config,lang){ } //run purge command if(s.group[e.ke].usedSpaceTimelapseFrames > (s.group[e.ke].sizeLimit * (s.group[e.ke].sizeLimitTimelapseFramesPercent / 100) * config.cron.deleteOverMaxOffset)){ - s.sqlQuery('SELECT * FROM `Timelapse Frames` WHERE ke=? AND details NOT LIKE \'%"archived":"1"%\' ORDER BY `time` ASC LIMIT 3',[e.ke],function(err,frames){ - deleteSetOfTimelapseFrames(err,frames,null,callback) - }) + s.knexQuery({ + action: "select", + columns: "*", + table: "Timelapse Frames", + where: [ + ['ke','=',e.ke], + ['details','NOT LIKE',`%"archived":"1"%`], + ], + orderBy: ['time','asc'], + limit: 3 + },(err,frames) => { + deleteSetOfTimelapseFrames(err,frames,null,callback) + }) }else{ callback() } @@ -239,9 +320,18 @@ module.exports = function(s,config,lang){ } //run purge command if(s.group[e.ke].usedSpaceFileBin > (s.group[e.ke].sizeLimit * (s.group[e.ke].sizeLimitFileBinPercent / 100) * config.cron.deleteOverMaxOffset)){ - s.sqlQuery('SELECT * FROM `Files` WHERE ke=? ORDER BY `time` ASC LIMIT 1',[e.ke],function(err,frames){ - deleteSetOfFileBinFiles(err,frames,null,callback) - }) + s.knexQuery({ + action: "select", + columns: "*", + table: "Files", + where: [ + ['ke','=',e.ke], + ], + orderBy: ['time','asc'], + limit: 1 + },(err,frames) => { + deleteSetOfFileBinFiles(err,frames,null,callback) + }) }else{ callback() } @@ -306,8 +396,19 @@ module.exports = function(s,config,lang){ s.userLog = function(e,x){ if(e.id && !e.mid)e.mid = e.id if(!x||!e.mid){return} - if((e.details&&e.details.sqllog==='1')||e.mid.indexOf('$')>-1){ - s.sqlQuery('INSERT INTO Logs (ke,mid,info) VALUES (?,?,?)',[e.ke,e.mid,s.s(x)]); + if( + (e.details && e.details.sqllog === '1') || + e.mid.indexOf('$') > -1 + ){ + s.knexQuery({ + action: "insert", + table: "Logs", + insert: { + ke: e.ke, + mid: e.mid, + info: s.s(x), + } + }) } s.tx({f:'log',ke:e.ke,mid:e.mid,log:x,time:s.timeObject()},'GRPLOG_'+e.ke); } @@ -343,13 +444,21 @@ module.exports = function(s,config,lang){ if(!s.group[e.ke].init){ s.group[e.ke].init={}; } - s.sqlQuery('SELECT * FROM Users WHERE ke=? AND details NOT LIKE ?',[e.ke,'%"sub"%'],function(ar,r){ + s.knexQuery({ + action: "select", + columns: "*", + table: "Users", + where: [ + ['ke','=',e.ke], + ['details','NOT LIKE',`%"sub"%`], + ] + },function(err,r) { if(r && r[0]){ r = r[0]; - ar = JSON.parse(r.details); + const details = JSON.parse(r.details); //load extenders s.loadGroupAppExtensions.forEach(function(extender){ - extender(r,ar) + extender(r,details) }) //disk Used Emitter if(!s.group[e.ke].diskUsedEmitter){ @@ -391,30 +500,57 @@ module.exports = function(s,config,lang){ var deleteVideos = function(){ //run purge command 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/1048576), - 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() - }) + s.knexQuery({ + action: "select", + columns: "*", + table: "Cloud Videos", + where: [ + ['status','!=','0'], + ['ke','=',e.ke], + ['details','LIKE',`%"type":"${storageType}"%`], + ], + orderBy: ['time','asc'], + limit: 2 + },function(err,videos) { + if(!videos)return console.log(err) + var whereQuery = [ + ['ke','=',e.ke], + [] + ] + var didOne = false + videos.forEach(function(video){ + video.dir = s.getVideoDirectory(video) + s.formattedTime(video.time) + '.' + video.ext + if(didOne){ + const whereGroup = [ + ['or','mid','=',video.mid], + ['time','=',video.time] + ] }else{ - finish() + didOne = false + const whereGroup = [ + ['mid','=',video.mid], + ['time','=',video.time] + ] } + whereQuery[1].push(whereGroup) + s.setCloudDiskUsedForGroup(e,{ + amount : -(video.size/1048576), + storageType : storageType + }) + s.deleteVideoFromCloudExtensionsRunner(e,storageType,video) }) + if(whereQuery[1].length > 0){ + s.knexQuery({ + action: "delete", + table: "Cloud Videos", + where: whereQuery + },() => { + deleteVideos() + }) + }else{ + finish() + } + }) }else{ finish() } @@ -425,22 +561,48 @@ module.exports = function(s,config,lang){ } //run purge command if(cloudDisk.usedSpaceTimelapseFrames > (cloudDisk.sizeLimit * (s.group[e.ke].sizeLimitTimelapseFramesPercent / 100) * config.cron.deleteOverMaxOffset)){ - s.sqlQuery('SELECT * FROM `Cloud Timelapse Frames` WHERE ke=? AND details NOT LIKE \'%"archived":"1"%\' ORDER BY `time` ASC LIMIT 3',[e.ke],function(err,frames){ - var framesToDelete = [] - var queryValues = [e.ke] + s.knexQuery({ + action: "select", + columns: "*", + table: "Cloud Timelapse Frames", + where: [ + ['ke','=',e.ke], + ['details','NOT LIKE',`%"archived":"1"%`], + ], + orderBy: ['time','asc'], + limit: 3 + },(err,frames) => { if(!frames)return console.log(err) + var whereQuery = [ + ['ke','=',e.ke], + [] + ] frames.forEach(function(frame){ frame.dir = s.getVideoDirectory(frame) + s.formattedTime(frame.time) + '.' + frame.ext - framesToDelete.push('(mid=? AND `time`=?)') - queryValues.push(frame.mid) - queryValues.push(frame.time) + if(didOne){ + const whereGroup = [ + ['or','mid','=',frame.mid], + ['time','=',frame.time] + ] + }else{ + didOne = false + const whereGroup = [ + ['mid','=',frame.mid], + ['time','=',frame.time] + ] + } + whereQuery[1].push(whereGroup) s.setCloudDiskUsedForGroup(e,{ amount : -(frame.size/1048576), storageType : storageType }) s.deleteVideoFromCloudExtensionsRunner(e,storageType,frame) }) - s.sqlQuery('DELETE FROM `Cloud Timelapse Frames` WHERE ke =? AND ('+framesToDelete+')',queryValues,function(){ + s.knexQuery({ + action: "delete", + table: "Cloud Timelapse Frames", + where: whereQuery + },() => { deleteTimelapseFrames(callback) }) }) @@ -513,60 +675,69 @@ module.exports = function(s,config,lang){ s.sendDiskUsedAmountToClients(e) }) } - Object.keys(ar).forEach(function(v){ - s.group[e.ke].init[v] = ar[v] + Object.keys(details).forEach(function(v){ + s.group[e.ke].init[v] = details[v] }) } }) } s.accountSettingsEdit = function(d,dontRunExtensions){ - s.sqlQuery('SELECT details FROM Users WHERE ke=? AND uid=?',[d.ke,d.uid],function(err,r){ - if(r&&r[0]){ - r=r[0]; - d.d=JSON.parse(r.details); - if(!d.d.sub || d.d.user_change !== "0"){ + s.knexQuery({ + action: "select", + columns: "details", + table: "Users", + where: [ + ['ke','=',d.ke], + ['uid','=',d.uid], + ] + },function(err,r) { + if(r && r[0]){ + r = r[0]; + const details = JSON.parse(r.details); + if(!details.sub || details.user_change !== "0"){ if(d.cnid){ - if(d.d.get_server_log === '1'){ + if(details.get_server_log === '1'){ s.clientSocketConnection[d.cnid].join('GRPLOG_'+d.ke) }else{ s.clientSocketConnection[d.cnid].leave('GRPLOG_'+d.ke) } } ///unchangeable from client side, so reset them in case they did. - d.form.details=JSON.parse(d.form.details) + var form = d.form + var formDetails = JSON.parse(form.details) if(!dontRunExtensions){ 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_ldap=d.d.use_ldap - d.form.details.landing_page=d.d.landing_page + formDetails.permissions = details.permissions + formDetails.edit_size = details.edit_size + formDetails.edit_days = details.edit_days + formDetails.use_admin = details.use_admin + formDetails.use_ldap = details.use_ldap + formDetails.landing_page = details.landing_page //check - if(d.d.edit_days == "0"){ - d.form.details.days = d.d.days; + if(details.edit_days == "0"){ + formDetails.days = details.days; } - if(d.d.edit_size == "0"){ - d.form.details.size = d.d.size; - d.form.details.addStorage = d.d.addStorage; + if(details.edit_size == "0"){ + formDetails.size = details.size; + formDetails.addStorage = details.addStorage; } - if(d.d.sub){ - d.form.details.sub=d.d.sub; - if(d.d.monitors){d.form.details.monitors=d.d.monitors;} - if(d.d.allmonitors){d.form.details.allmonitors=d.d.allmonitors;} - if(d.d.monitor_create){d.form.details.monitor_create=d.d.monitor_create;} - if(d.d.video_delete){d.form.details.video_delete=d.d.video_delete;} - if(d.d.video_view){d.form.details.video_view=d.d.video_view;} - if(d.d.monitor_edit){d.form.details.monitor_edit=d.d.monitor_edit;} - if(d.d.size){d.form.details.size=d.d.size;} - if(d.d.days){d.form.details.days=d.d.days;} - delete(d.form.details.mon_groups) + if(details.sub){ + formDetails.sub = details.sub; + if(details.monitors){formDetails.monitors = details.monitors;} + if(details.allmonitors){formDetails.allmonitors = details.allmonitors;} + if(details.monitor_create){formDetails.monitor_create = details.monitor_create;} + if(details.video_delete){formDetails.video_delete = details.video_delete;} + if(details.video_view){formDetails.video_view = details.video_view;} + if(details.monitor_edit){formDetails.monitor_edit = details.monitor_edit;} + if(details.size){formDetails.size = details.size;} + if(details.days){formDetails.days = details.days;} + delete(formDetails.mon_groups) } - var newSize = parseFloat(d.form.details.size) || 10000 + var newSize = parseFloat(formDetails.size) || 10000 //load addStorageUse var currentStorageNumber = 0 var readStorageArray = function(){ @@ -581,7 +752,7 @@ module.exports = function(s,config,lang){ readStorageArray() return } - var detailContainer = d.form.details || s.group[r.ke].init + var detailContainer = formDetails || s.group[r.ke].init var storageId = path var detailsContainerAddStorage = s.parseJSON(detailContainer.addStorage) if(!s.group[d.ke].addStorageUse[storageId])s.group[d.ke].addStorageUse[storageId] = {} @@ -597,20 +768,31 @@ module.exports = function(s,config,lang){ } readStorageArray() /// - d.form.details = JSON.stringify(s.mergeDeep(d.d,d.form.details)) + formDetails = JSON.stringify(s.mergeDeep(details,formDetails)) /// - d.set=[],d.ar=[]; - if(d.form.pass&&d.form.pass!==''){d.form.pass=s.createHash(d.form.pass);}else{delete(d.form.pass)}; - delete(d.form.password_again); - d.for=Object.keys(d.form); - d.for.forEach(function(v){ - d.set.push(v+'=?'),d.ar.push(d.form[v]); - }); - 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) + const updateQuery = {} + if(form.pass && form.pass !== ''){ + form.pass = s.createHash(form.pass) + }else{ + delete(form.pass) + } + delete(form.password_again) + Object.keys(form).forEach(function(key){ + const value = form[key] + updateQuery[key] = value + }) + s.knexQuery({ + action: "update", + table: "Users", + update: updateQuery, + where: [ + ['ke','=',d.ke], + ['uid','=',d.uid], + ] + },() => { + if(!details.sub){ + var user = Object.assign(form,{ke : d.ke}) + var userDetails = JSON.parse(formDetails) s.group[d.ke].sizeLimit = parseFloat(newSize) if(!dontRunExtensions){ s.onAccountSaveExtensions.forEach(function(extender){ @@ -622,7 +804,7 @@ module.exports = function(s,config,lang){ s.loadGroupApps(d) } } - if(d.cnid)s.tx({f:'user_settings_change',uid:d.uid,ke:d.ke,form:d.form},d.cnid) + if(d.cnid)s.tx({f:'user_settings_change',uid:d.uid,ke:d.ke,form:form},d.cnid) }) } } @@ -630,7 +812,17 @@ module.exports = function(s,config,lang){ } s.findPreset = function(presetQueryVals,callback){ //presetQueryVals = [ke, type, name] - s.sqlQuery("SELECT * FROM Presets WHERE ke=? AND type=? AND name=? LIMIT 1",presetQueryVals,function(err,presets){ + s.knexQuery({ + action: "select", + columns: "*", + table: "Presets", + where: [ + ['ke','=',presetQueryVals[0]], + ['type','=',presetQueryVals[1]], + ['name','=',presetQueryVals[2]], + ], + limit: 1 + },function(err,presets) { var preset var notFound = false if(presets && presets[0]){ diff --git a/libs/videoDropInServer.js b/libs/videoDropInServer.js index 12200b89..285427b9 100644 --- a/libs/videoDropInServer.js +++ b/libs/videoDropInServer.js @@ -31,7 +31,18 @@ module.exports = function(s,config,lang,app,io){ details.dir = monitor.details.dir } var timeNow = new Date(s.nameToTime(filename)) - s.sqlQuery('INSERT INTO `Timelapse Frames` (ke,mid,details,filename,size,time) VALUES (?,?,?,?,?,?)',[ke,mid,s.s(details),filename,fileStats.size,timeNow]) + s.knexQuery({ + action: "insert", + table: "Timelapse Frames", + insert: { + ke: ke, + mid: mid, + details: s.s(details), + filename: filename, + size: fileStats.size, + time: timeNow, + } + }) s.setDiskUsedForGroup(monitor,fileStats.size / 1048576) } // else{ From 70c125db567f29356cd9a5a05e0c0a515265fa64 Mon Sep 17 00:00:00 2001 From: Moe Date: Sat, 11 Jul 2020 00:33:25 -0700 Subject: [PATCH 017/175] sqlQuery Conversion : videos --- libs/videos.js | 125 +++++++++++++++++++++++++++++++++++-------------- 1 file changed, 90 insertions(+), 35 deletions(-) diff --git a/libs/videos.js b/libs/videos.js index e3bf0c5e..56895d1b 100644 --- a/libs/videos.js +++ b/libs/videos.js @@ -64,17 +64,20 @@ module.exports = function(s,config,lang){ k.details.dir = e.details.dir } if(config.useUTC === true)k.details.isUTC = config.useUTC; - var save = [ - e.mid, - e.ke, - k.startTime, - e.ext, - 1, - s.s(k.details), - k.filesize, - k.endTime, - ] - s.sqlQuery('INSERT INTO Videos (mid,ke,time,ext,status,details,size,end) VALUES (?,?,?,?,?,?,?,?)',save,function(err){ + s.knexQuery({ + action: "insert", + table: "Videos", + insert: { + ke: e.ke, + mid: e.mid, + time: k.startTime, + ext: e.ext, + status: 1, + details: s.s(k.details), + size: k.filesize, + end: k.endTime, + } + },(err) => { if(callback)callback(err) fs.chmod(k.dir+k.file,0o777,function(err){ @@ -211,8 +214,17 @@ module.exports = function(s,config,lang){ time = e.time } time = new Date(time) - var queryValues = [e.id,e.ke,time]; - s.sqlQuery('SELECT * FROM Videos WHERE `mid`=? AND `ke`=? AND `time`=?',queryValues,function(err,r){ + const whereQuery = [ + ['ke','=',e.ke], + ['mid','=',e.id], + ['time','=',time], + ] + s.knexQuery({ + action: "select", + columns: "*", + table: "Videos", + where: whereQuery + },function(err,r) { if(r && r[0]){ r = r[0] fs.chmod(e.dir+filename,0o777,function(err){ @@ -233,7 +245,11 @@ module.exports = function(s,config,lang){ }else{ s.setDiskUsedForGroup(e,-(r.size / 1048576)) } - s.sqlQuery('DELETE FROM Videos WHERE `mid`=? AND `ke`=? AND `time`=?',queryValues,function(err){ + s.knexQuery({ + action: "delete", + table: "Videos", + where: whereQuery + },function(err) { if(err){ s.systemLog(lang['File Delete Error'] + ' : '+e.ke+' : '+' : '+e.id,err) } @@ -254,9 +270,8 @@ module.exports = function(s,config,lang){ } s.deleteListOfVideos = function(videos){ var deleteSetOfVideos = function(videos){ - var query = 'DELETE FROM Videos WHERE ' - var videoQuery = [] - var queryValues = [] + const whereQuery = [] + var didOne = false; videos.forEach(function(video){ s.checkDetails(video) //e = video object @@ -277,7 +292,7 @@ module.exports = function(s,config,lang){ time = video.time } time = new Date(time) - fs.chmod(video.dir+filename,0o777,function(err){ + fs.chmod(video.dir + filename,0o777,function(err){ s.tx({ f: 'video_delete', filename: filename, @@ -295,19 +310,30 @@ module.exports = function(s,config,lang){ }else{ s.setDiskUsedForGroup(video,-(video.size / 1048576)) } - fs.unlink(video.dir+filename,function(err){ - fs.stat(video.dir+filename,function(err){ + fs.unlink(video.dir + filename,function(err){ + fs.stat(video.dir + filename,function(err){ if(!err){ - s.file('delete',video.dir+filename) + s.file('delete',video.dir + filename) } }) }) }) - videoQuery.push('(`mid`=? AND `ke`=? AND `time`=?)') - queryValues = queryValues.concat([video.id,video.ke,time]) + if(!didOne){ + didOne = true + whereQuery.push(['mid','=',video.id]) + }else{ + whereQuery.push(['or','mid','=',video.id]) + } + whereQuery.push( + ['ke','=',video.ke], + ['time','=',time], + ) }) - query += videoQuery.join(' OR ') - s.sqlQuery(query,queryValues,function(err){ + s.knexQuery({ + action: "delete", + table: "Videos", + where: whereQuery + },(err) => { if(err){ s.systemLog(lang['List of Videos Delete Error'],err) } @@ -339,11 +365,24 @@ module.exports = function(s,config,lang){ s.deleteVideoFromCloud = function(e){ // e = video object s.checkDetails(e) - 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){ + const whereQuery = [ + ['ke','=',e.ke], + ['mid','=',e.id], + ['time','=',new Date(e.time)], + ] + s.knexQuery({ + action: "select", + columns: "*", + table: "Cloud Videos", + where: whereQuery + },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.knexQuery({ + action: "delete", + table: "Cloud Videos", + where: whereQuery + },function(err,r) { s.deleteVideoFromCloudExtensionsRunner(e,r) }) }else{ @@ -375,12 +414,17 @@ module.exports = function(s,config,lang){ } fiveRecentFiles.forEach(function(filename){ if(/T[0-9][0-9]-[0-9][0-9]-[0-9][0-9]./.test(filename)){ - var queryValues = [ - monitor.ke, - monitor.mid, - s.nameToTime(filename) - ] - s.sqlQuery('SELECT * FROM Videos WHERE ke=? AND mid=? AND time=? LIMIT 1',queryValues,function(err,rows){ + s.knexQuery({ + action: "select", + columns: "*", + table: "Videos", + where: [ + ['ke','=',monitor.ke], + ['mid','=',monitor.mid], + ['time','=',s.nameToTime(filename)], + ], + limit: 1 + },function(err,rows) { if(!err && (!rows || !rows[0])){ ++orphanedFilesCount var video = rows[0] @@ -487,7 +531,18 @@ module.exports = function(s,config,lang){ var timeNow = new Date() var fileStats = fs.statSync(finalMp4OutputLocation) var details = {} - s.sqlQuery('INSERT INTO `Files` (ke,mid,details,name,size,time) VALUES (?,?,?,?,?,?)',[ke,mid,s.s(details),finalFileName + '.mp4',fileStats.size,timeNow]) + s.knexQuery({ + action: "insert", + table: "Files", + insert: { + ke: ke, + mid: mid, + details: s.s(details), + name: finalFileName + '.mp4', + size: fileStats.size, + time: timeNow, + } + }) s.setDiskUsedForGroup({ke: ke},fileStats.size / 1048576,'fileBin') fs.unlink(commandTempLocation,function(){ From 556ea34ba8cd00fa68aeafd4dffb0ca847a81a43 Mon Sep 17 00:00:00 2001 From: Moe Date: Sat, 11 Jul 2020 00:39:11 -0700 Subject: [PATCH 018/175] sqlQuery Conversion : minor cleanup --- libs/scheduler.js | 2 +- libs/videos.js | 12 ++++++------ 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/libs/scheduler.js b/libs/scheduler.js index 05fde71b..9b14db7c 100644 --- a/libs/scheduler.js +++ b/libs/scheduler.js @@ -7,7 +7,7 @@ module.exports = function(s,config,lang,app,io){ action: "select", columns: "*", table: "Schedules" - },function(err,rows) { + },(err,rows) => { rows.forEach(function(schedule){ s.updateSchedule(schedule) }) diff --git a/libs/videos.js b/libs/videos.js index 56895d1b..2c038bf2 100644 --- a/libs/videos.js +++ b/libs/videos.js @@ -224,7 +224,7 @@ module.exports = function(s,config,lang){ columns: "*", table: "Videos", where: whereQuery - },function(err,r) { + },(err,r) => { if(r && r[0]){ r = r[0] fs.chmod(e.dir+filename,0o777,function(err){ @@ -249,7 +249,7 @@ module.exports = function(s,config,lang){ action: "delete", table: "Videos", where: whereQuery - },function(err) { + },(err) => { if(err){ s.systemLog(lang['File Delete Error'] + ' : '+e.ke+' : '+' : '+e.id,err) } @@ -375,14 +375,14 @@ module.exports = function(s,config,lang){ columns: "*", table: "Cloud Videos", where: whereQuery - },function(err,r) { + },(err,r) => { if(r&&r[0]){ r = r[0] s.knexQuery({ action: "delete", table: "Cloud Videos", where: whereQuery - },function(err,r) { + },(err,r) => { s.deleteVideoFromCloudExtensionsRunner(e,r) }) }else{ @@ -424,13 +424,13 @@ module.exports = function(s,config,lang){ ['time','=',s.nameToTime(filename)], ], limit: 1 - },function(err,rows) { + },(err,rows) => { if(!err && (!rows || !rows[0])){ ++orphanedFilesCount var video = rows[0] s.insertCompletedVideo(monitor,{ file : filename - },function(){ + },() => { fileComplete() }) }else{ From 69f038a4777b80eb1d56b8d1e9a0686d3b4e34ed Mon Sep 17 00:00:00 2001 From: Moe Date: Sat, 11 Jul 2020 11:14:30 -0700 Subject: [PATCH 019/175] sqlQuery Conversion : webServerAdminPaths.js --- libs/webServerAdminPaths.js | 188 +++++++++++++++++++++++++++--------- 1 file changed, 142 insertions(+), 46 deletions(-) diff --git a/libs/webServerAdminPaths.js b/libs/webServerAdminPaths.js index 8c5548c3..232684b4 100644 --- a/libs/webServerAdminPaths.js +++ b/libs/webServerAdminPaths.js @@ -25,15 +25,18 @@ module.exports = function(s,config,lang,app){ var mail = form.mail || s.getPostData(req,'mail',false) if(form){ var keys = ['details'] - var condition = [] - var value = [] - keys.forEach(function(v){ - condition.push(v+'=?') - if(form[v] instanceof Object)form[v] = JSON.stringify(form[v]) - value.push(form[v]) + const updateQuery = { + details: s.stringJSON(form.details) + } + s.knexQuery({ + action: "update", + table: "Users", + update: updateQuery, + where: [ + ['ke','=',req.params.ke], + ['uid','=',uid], + ] }) - value = value.concat([req.params.ke,uid]) - s.sqlQuery("UPDATE Users SET "+condition.join(',')+" WHERE ke=? AND uid=?",value) s.tx({ f: 'edit_sub_account', ke: req.params.ke, @@ -42,7 +45,15 @@ module.exports = function(s,config,lang,app){ form: form },'ADM_'+req.params.ke) endData.ok = true - s.sqlQuery("SELECT * FROM API WHERE ke=? AND uid=?",[req.params.ke,uid],function(err,rows){ + s.knexQuery({ + action: "select", + columns: "*", + table: "API", + where: [ + ['ke','=',req.params.ke], + ['uid','=',uid], + ] + },function(err,rows){ if(rows && rows[0]){ rows.forEach(function(row){ delete(s.api[row.code]) @@ -71,13 +82,37 @@ module.exports = function(s,config,lang,app){ var form = s.getPostData(req) || {} var uid = form.uid || s.getPostData(req,'uid',false) var mail = form.mail || s.getPostData(req,'mail',false) - s.sqlQuery('DELETE FROM Users WHERE uid=? AND ke=? AND mail=?',[uid,req.params.ke,mail]) - s.sqlQuery("SELECT * FROM API WHERE ke=? AND uid=?",[req.params.ke,uid],function(err,rows){ + s.knexQuery({ + action: "delete", + table: "Users", + update: monitorQuery, + where: [ + ['uid','=',uid], + ['ke','=',req.params.ke], + ['mail','=',mail], + ] + }) + s.knexQuery({ + action: "select", + columns: "*", + table: "API", + where: [ + ['ke','=',req.params.ke], + ['uid','=',uid], + ] + },function(err,rows){ if(rows && rows[0]){ rows.forEach(function(row){ delete(s.api[row.code]) }) - s.sqlQuery('DELETE FROM API WHERE uid=? AND ke=?',[uid,req.params.ke]) + s.knexQuery({ + action: "delete", + table: "API", + where: [ + ['uid','=',uid], + ['ke','=',req.params.ke], + ] + }) } }) s.tx({ @@ -112,8 +147,15 @@ module.exports = function(s,config,lang,app){ var form = s.getPostData(req) if(form.mail !== '' && form.pass !== ''){ if(form.pass === form.password_again || form.pass === form.pass_again){ - s.sqlQuery('SELECT * FROM Users WHERE mail=?',[form.mail],function(err,r) { - if(r&&r[0]){ + s.knexQuery({ + action: "select", + columns: "*", + table: "Users", + where: [ + ['mail','=',form.mail], + ] + },function(err,r){ + if(r && r[0]){ //found one exist endData.msg = 'Email address is in use.' }else{ @@ -125,7 +167,17 @@ module.exports = function(s,config,lang,app){ sub: "1", allmonitors: "1" }) - s.sqlQuery('INSERT INTO Users (ke,uid,mail,pass,details) VALUES (?,?,?,?,?)',[req.params.ke,newId,form.mail,s.createHash(form.pass),details]) + s.knexQuery({ + action: "insert", + table: "Users", + insert: { + ke: req.params.ke, + uid: newId, + mail: form.mail, + pass: s.createHash(form.pass), + details: details, + } + }) s.tx({ f: 'add_sub_account', details: details, @@ -199,8 +251,22 @@ module.exports = function(s,config,lang,app){ s.userLog(s.group[req.params.ke].rawMonitorConfigurations[req.params.id],{type:'Monitor Deleted',msg:'by user : '+user.uid}); req.params.delete=1;s.camera('stop',req.params); s.tx({f:'monitor_delete',uid:user.uid,mid:req.params.id,ke:req.params.ke},'GRP_'+req.params.ke); - s.sqlQuery('DELETE FROM Monitors WHERE ke=? AND mid=?',[req.params.ke,req.params.id]) - // s.sqlQuery('DELETE FROM Files WHERE ke=? AND mid=?',[req.params.ke,req.params.id]) + s.knexQuery({ + action: "delete", + table: "Monitors", + where: [ + ['ke','=',req.params.ke], + ['mid','=',req.params.id], + ] + }) + // s.knexQuery({ + // action: "delete", + // table: "Files", + // where: [ + // ['ke','=',req.params.ke], + // ['mid','=',req.params.id], + // ] + // }) if(req.query.deleteFiles === 'true'){ //videos s.dir.addStorage.forEach(function(v,n){ @@ -250,28 +316,28 @@ module.exports = function(s,config,lang,app){ } var form = s.getPostData(req) if(form){ - var insert = { + const insertQuery = { ke : req.params.ke, uid : user.uid, code : s.gid(30), ip : form.ip, details : s.stringJSON(form.details) } - var escapes = [] - Object.keys(insert).forEach(function(column){ - escapes.push('?') - }); - s.sqlQuery('INSERT INTO API ('+Object.keys(insert).join(',')+') VALUES ('+escapes.join(',')+')',Object.values(insert),function(err,r){ - insert.time = s.formattedTime(new Date,'YYYY-DD-MM HH:mm:ss'); + s.knexQuery({ + action: "insert", + table: "API", + insert: insertQuery + },(err,r) => { + insertQuery.time = s.formattedTime(new Date,'YYYY-DD-MM HH:mm:ss'); if(!err){ s.tx({ f: 'api_key_added', uid: user.uid, - form: insert + form: insertQuery },'GRP_' + req.params.ke) endData.ok = true } - endData.api = insert + endData.api = insertQuery s.closeJsonResponse(res,endData) }) }else{ @@ -305,16 +371,15 @@ module.exports = function(s,config,lang,app){ s.closeJsonResponse(res,endData) return } - var row = { - ke : req.params.ke, - uid : user.uid, - code : form.code - } - var where = [] - Object.keys(row).forEach(function(column){ - where.push(column+'=?') - }) - s.sqlQuery('DELETE FROM API WHERE '+where.join(' AND '),Object.values(row),function(err,r){ + s.knexQuery({ + action: "delete", + table: "API", + where: [ + ['ke','=',req.params.ke], + ['uid','=',user.uid], + ['code','=',form.code], + ] + },(err,r) => { if(!err){ s.tx({ f: 'api_key_deleted', @@ -345,15 +410,16 @@ module.exports = function(s,config,lang,app){ var endData = { ok : false } - var row = { + const whereQuery = { ke : req.params.ke, uid : user.uid } - var where = [] - Object.keys(row).forEach(function(column){ - where.push(column+'=?') - }) - s.sqlQuery('SELECT * FROM API WHERE '+where.join(' AND '),Object.values(row),function(err,rows){ + s.knexQuery({ + action: "select", + columns: "*", + table: "API", + where: whereQuery + },function(err,rows) { if(rows && rows[0]){ rows.forEach(function(row){ row.details = JSON.parse(row.details) @@ -383,7 +449,15 @@ module.exports = function(s,config,lang,app){ s.closeJsonResponse(res,endData) return } - s.sqlQuery("SELECT * FROM Presets WHERE ke=? AND type=?",[req.params.ke,'monitorStates'],function(err,presets){ + s.knexQuery({ + action: "select", + columns: "*", + table: "Presets", + where: [ + ['ke','=',req.params.ke], + ['type','=','monitorStates'], + ] + },function(err,presets) { if(presets && presets[0]){ endData.ok = true presets.forEach(function(preset){ @@ -435,7 +509,11 @@ module.exports = function(s,config,lang,app){ details: s.s(details), type: 'monitorStates' } - s.sqlQuery('INSERT INTO Presets ('+Object.keys(insertData).join(',')+') VALUES (?,?,?,?)',Object.values(insertData)) + s.knexQuery({ + action: "insert", + table: "Monitors", + insert: insertData + }) s.tx({ f: 'add_group_state', details: details, @@ -447,7 +525,17 @@ module.exports = function(s,config,lang,app){ var details = Object.assign(preset.details,{ monitors : form.monitors }) - s.sqlQuery('UPDATE Presets SET details=? WHERE ke=? AND name=?',[s.s(details),req.params.ke,req.params.stateName]) + s.knexQuery({ + action: "update", + table: "Presets", + update: { + details: s.s(details) + }, + where: [ + ['ke','=',req.params.ke], + ['name','=',req.params.stateName], + ] + }) s.tx({ f: 'edit_group_state', details: details, @@ -465,7 +553,15 @@ module.exports = function(s,config,lang,app){ endData.msg = user.lang['State Configuration Not Found'] s.closeJsonResponse(res,endData) }else{ - s.sqlQuery('DELETE FROM Presets WHERE ke=? AND name=?',[req.params.ke,req.params.stateName],function(err){ + s.knexQuery({ + action: "delete", + table: "Presets", + update: monitorQuery, + where: [ + ['ke','=',req.params.ke], + ['name','=',req.params.stateName], + ] + },(err) => { if(!err){ endData.msg = lang["Deleted State Configuration"] endData.ok = true From f1fc729435702384fc93bf207b5700d5378e9b6d Mon Sep 17 00:00:00 2001 From: Moe Date: Sat, 11 Jul 2020 13:16:01 -0700 Subject: [PATCH 020/175] sqlQuery Conversion : minor cleanup --- libs/auth.js | 10 +++++----- libs/monitor.js | 2 +- libs/notification.js | 4 ++-- libs/socketio.js | 24 ++++++++++++------------ libs/timelapse.js | 2 +- libs/user.js | 4 ++-- 6 files changed, 23 insertions(+), 23 deletions(-) diff --git a/libs/auth.js b/libs/auth.js index d16e37d7..edd8822c 100644 --- a/libs/auth.js +++ b/libs/auth.js @@ -16,7 +16,7 @@ module.exports = function(s,config,lang){ ['uid','=',params.uid], ['ke','=',params.ke], ] - },function(err,r) { + },(err,r) => { if(!r)r = [] var user = r[0] callback(err,user) @@ -31,7 +31,7 @@ module.exports = function(s,config,lang){ ['auth','=',params.auth], ['ke','=',params.ke], ] - },function(err,r) { + },(err,r) => { if(!r)r = [] var user = r[0] callback(err,user) @@ -50,7 +50,7 @@ module.exports = function(s,config,lang){ ['pass','=',s.createHash(params.password)], ], limit: 1 - },function(err,r) { + },(err,r) => { if(!r)r = [] var user = r[0] callback(err,user) @@ -66,7 +66,7 @@ module.exports = function(s,config,lang){ ['code','=',params.auth], ['ke','=',params.ke], ] - },function(err,r) { + },(err,r) => { if(!r)r = [] var apiKey = r[0] callback(err,apiKey) @@ -268,7 +268,7 @@ module.exports = function(s,config,lang){ where: [ ['details','NOT LIKE','%"sub"%'], ] - },function(err,r) { + },(err,r) => { adminUsersSelected = r success() }) diff --git a/libs/monitor.js b/libs/monitor.js index 1892e32c..74f3dfa1 100644 --- a/libs/monitor.js +++ b/libs/monitor.js @@ -1410,7 +1410,7 @@ module.exports = function(s,config,lang){ ['ke','=',form.ke], ['mid','=',form.mid], ] - },function(err,r) { + },(err,r) => { var affectMonitor = false var monitorQuery = {} var txData = { diff --git a/libs/notification.js b/libs/notification.js index 9ef37aa3..7c9cc089 100644 --- a/libs/notification.js +++ b/libs/notification.js @@ -215,7 +215,7 @@ module.exports = function(s,config,lang){ ['ke','=',e.ke], ['details','NOT LIKE','%"sub"%'], ] - },function(err,r) { + },(err,r) => { r = r[0] var mailOptions = { from: config.mail.from, // sender address @@ -299,7 +299,7 @@ module.exports = function(s,config,lang){ ['ke','=',d.ke], ['details','NOT LIKE','%"sub"%'], ] - },function(err,r) { + },(err,r) => { r=r[0]; var detector_mail_timeout if(!d.mon.details.detector_mail_timeout||d.mon.details.detector_mail_timeout===''){ diff --git a/libs/socketio.js b/libs/socketio.js index 16cbe2a2..aa202b40 100644 --- a/libs/socketio.js +++ b/libs/socketio.js @@ -62,7 +62,7 @@ module.exports = function(s,config,lang,io){ ['auth','=',options.auth], ['uid','=',options.uid], ] - },function(err,r) { + },(err,r) => { if(r&&r[0]){ resolve(r) }else{ @@ -75,7 +75,7 @@ module.exports = function(s,config,lang,io){ ['code','=',options.auth], ['uid','=',options.uid], ] - },function(err,r) { + },(err,r) => { if(r && r[0]){ r = r[0] r.details = JSON.parse(r.details) @@ -88,7 +88,7 @@ module.exports = function(s,config,lang,io){ ['ke','=',options.ke], ['uid','=',options.uid], ] - },function(err,r) { + },(err,r) => { if(r && r[0]){ resolve(r) }else{ @@ -382,7 +382,7 @@ module.exports = function(s,config,lang,io){ where: [ ['ke','=',d.ke], ] - },function(err,r) { + },(err,r) => { if(r && r[0]){ r.forEach(function(monitor){ s.cameraSendSnapshot({mid:monitor.mid,ke:monitor.ke,mon:monitor},{useIcon: true}) @@ -414,7 +414,7 @@ module.exports = function(s,config,lang,io){ columns: "*", table: "Users", where: whereQuery - },function(err,r) { + },(err,r) => { if(r && r[0]){ details = JSON.parse(r[0].details) details.monitorOrder = d.monitorOrder @@ -437,7 +437,7 @@ module.exports = function(s,config,lang,io){ columns: "*", table: "Users", where: whereQuery - },function(err,r) { + },(err,r) => { if(r && r[0]){ details = JSON.parse(r[0].details) details.monitorListOrder = d.monitorListOrder @@ -467,7 +467,7 @@ module.exports = function(s,config,lang,io){ ['uid','=',d.uid], ], limit: 1 - },function(err,r) { + },(err,r) => { if(r && r[0]){ r = r[0]; d.d=JSON.parse(r.details); @@ -563,7 +563,7 @@ module.exports = function(s,config,lang,io){ where: eventWhereQuery, orderBy: ['time','desc'], limit: d.eventLimit - },function(err,r) { + },(err,r) => { if(err){ console.error(err) callback([]) @@ -619,7 +619,7 @@ module.exports = function(s,config,lang,io){ where: videoWhereQuery, orderBy: ['time','desc'], limit: d.videoLimit || '100' - },function(err,r) { + },(err,r) => { if(err){ console.error(err) setTimeout(function(){ @@ -700,7 +700,7 @@ module.exports = function(s,config,lang,io){ ['mid','=',d.id], ], limit: 1 - },function(err,r) { + },(err,r) => { if(r && r[0]){ r = r[0] s.camera(d.ff,{type:r.type,url:s.buildMonitorUrl(r),id:d.id,mode:d.ff,ke:cn.ke}); @@ -810,7 +810,7 @@ module.exports = function(s,config,lang,io){ ['uid','=',d.uid], ], limit: 1 - },function(err,r) { + },(err,r) => { if(r && r[0]){ r = r[0]; if(!s.group[d.ke]){s.group[d.ke]={users:{}}} @@ -842,7 +842,7 @@ module.exports = function(s,config,lang,io){ ['uid','=',d.uid], ], limit: 1 - },function(err,r) { + },(err,r) => { if(r && r[0]){ r = r[0] cn.ke=d.ke,cn.uid=d.uid,cn.auth=d.auth; diff --git a/libs/timelapse.js b/libs/timelapse.js index a6f95230..259c7268 100644 --- a/libs/timelapse.js +++ b/libs/timelapse.js @@ -53,7 +53,7 @@ module.exports = function(s,config,lang,app,io){ where: whereQuery, orderBy: ['time','desc'], limit: frameLimit || '500' - },function(err,r) { + },(err,r) => { if(err){ callback({ ok: false, diff --git a/libs/user.js b/libs/user.js index 7bf76b8b..51a62f93 100644 --- a/libs/user.js +++ b/libs/user.js @@ -452,7 +452,7 @@ module.exports = function(s,config,lang){ ['ke','=',e.ke], ['details','NOT LIKE',`%"sub"%`], ] - },function(err,r) { + },(err,r) => { if(r && r[0]){ r = r[0]; const details = JSON.parse(r.details); @@ -690,7 +690,7 @@ module.exports = function(s,config,lang){ ['ke','=',d.ke], ['uid','=',d.uid], ] - },function(err,r) { + },(err,r) => { if(r && r[0]){ r = r[0]; const details = JSON.parse(r.details); From 9b18fb39bae5a792af5501f8d4ac07855b12fa72 Mon Sep 17 00:00:00 2001 From: Moe Date: Sat, 11 Jul 2020 14:00:14 -0700 Subject: [PATCH 021/175] sqlQuery Conversion : webServerPaths.js --- libs/webServerPaths.js | 1120 ++++++++++++++++++++-------------------- 1 file changed, 550 insertions(+), 570 deletions(-) diff --git a/libs/webServerPaths.js b/libs/webServerPaths.js index 9646791b..45b8ad81 100644 --- a/libs/webServerPaths.js +++ b/libs/webServerPaths.js @@ -85,7 +85,18 @@ module.exports = function(s,config,lang,app,io){ if(s.group[req.params.ke]&&s.group[req.params.ke].users[req.params.auth]){ 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]) + s.knexQuery({ + action: "update", + table: "Users", + update: { + auth: '', + }, + where: [ + ['auth','=',req.params.auth], + ['ke','=',req.params.ke], + ['uid','=',req.params.id], + ] + }) res.end(s.prettyPrint({ok:true,msg:'You have been logged out, session key is now inactive.'})) }else{ res.end(s.prettyPrint({ok:false,msg:'This group key does not exist or this user is not logged in.'})) @@ -236,16 +247,23 @@ module.exports = function(s,config,lang,app,io){ ip: req.ip } } - if(board==='super'){ + if(board === 'super'){ s.userLog(logTo,logData) }else{ - s.sqlQuery('SELECT ke,uid,details FROM Users WHERE mail=?',[req.body.mail],function(err,r) { - if(r&&r[0]){ + s.knexQuery({ + action: "select", + columns: "ke,uid,details", + table: "Users", + where: [ + ['mail','=',req.body.mail], + ] + },(err,r) => { + if(r && r[0]){ r = r[0] - r.details=JSON.parse(r.details); - r.lang=s.getLanguageFile(r.details.lang) - logData.id=r.uid - logData.type=r.lang['Authentication Failed'] + r.details = JSON.parse(r.details) + r.lang = s.getLanguageFile(r.details.lang) + logData.id = r.uid + logData.type = r.lang['Authentication Failed'] logTo.ke = r.ke } s.userLog(logTo,logData) @@ -255,8 +273,16 @@ module.exports = function(s,config,lang,app,io){ checkRoute = function(r){ switch(req.body.function){ case'cam': - s.sqlQuery('SELECT * FROM Monitors WHERE ke=? AND type=?',[r.ke,"dashcam"],function(err,rr){ - req.resp.mons=rr; + s.knexQuery({ + action: "select", + columns: "*", + table: "Monitors", + where: [ + ['ke','=',r.ke], + ['type','=','dashcam'], + ] + },(err,rr) => { + req.resp.mons = rr renderPage(config.renderPaths.dashcam,{ // config: s.getConfigWithBranding(req.hostname), $user: req.resp, @@ -267,7 +293,15 @@ module.exports = function(s,config,lang,app,io){ }) break; case'streamer': - s.sqlQuery('SELECT * FROM Monitors WHERE ke=? AND type=?',[r.ke,"socket"],function(err,rr){ + s.knexQuery({ + action: "select", + columns: "*", + table: "Monitors", + where: [ + ['ke','=',r.ke], + ['type','=','socket'], + ] + },(err,rr) => { req.resp.mons=rr; renderPage(config.renderPaths.streamer,{ // config: s.getConfigWithBranding(req.hostname), @@ -280,8 +314,23 @@ module.exports = function(s,config,lang,app,io){ break; case'admin': if(!r.details.sub){ - s.sqlQuery('SELECT uid,mail,details FROM Users WHERE ke=? AND details LIKE \'%"sub"%\'',[r.ke],function(err,rr) { - s.sqlQuery('SELECT * FROM Monitors WHERE ke=?',[r.ke],function(err,rrr) { + s.knexQuery({ + action: "select", + columns: "uid,mail,details", + table: "Users", + where: [ + ['ke','=',r.ke], + ['details','LIKE','%"sub"%'], + ] + },(err,rr) => { + s.knexQuery({ + action: "select", + columns: "*", + table: "Monitors", + where: [ + ['ke','=',r.ke], + ] + },(err,rrr) => { renderPage(config.renderPaths.admin,{ config: s.getConfigWithBranding(req.hostname), $user: req.resp, @@ -333,11 +382,30 @@ module.exports = function(s,config,lang,app,io){ } if(req.body.mail&&req.body.pass){ req.default=function(){ - s.sqlQuery('SELECT * FROM Users WHERE mail=? AND pass=?',[req.body.mail,s.createHash(req.body.pass)],function(err,r) { + s.knexQuery({ + action: "select", + columns: "*", + table: "Users", + where: [ + ['mail','=',req.body.mail], + ['pass','=',s.createHash(req.body.pass)], + ], + limit: 1 + },(err,r) => { req.resp={ok:false}; if(!err&&r&&r[0]){ r=r[0];r.auth=s.md5(s.gid()); - s.sqlQuery("UPDATE Users SET auth=? WHERE ke=? AND uid=?",[r.auth,r.ke,r.uid]) + s.knexQuery({ + action: "update", + table: "Users", + update: { + auth: r.auth + }, + where: [ + ['ke','=',r.ke], + ['uid','=',r.uid], + ] + }) req.resp={ok:true,auth_token:r.auth,ke:r.ke,uid:r.uid,mail:r.mail,details:r.details}; r.details=JSON.parse(r.details); r.lang=s.getLanguageFile(r.details.lang) @@ -380,7 +448,15 @@ module.exports = function(s,config,lang,app,io){ } } if(r.details.sub){ - s.sqlQuery('SELECT details FROM Users WHERE ke=? AND details NOT LIKE ?',[r.ke,'%"sub"%'],function(err,rr) { + s.knexQuery({ + action: "select", + columns: "details", + table: "Users", + where: [ + ['ke','=',r.ke], + ['details','NOT LIKE','%"sub"%'], + ], + },function(err,rr) { if(rr && rr[0]){ rr=rr[0]; rr.details=JSON.parse(rr.details); @@ -400,7 +476,15 @@ module.exports = function(s,config,lang,app,io){ }) } if(LdapAuth&&req.body.function==='ldap'&&req.body.key!==''){ - s.sqlQuery('SELECT * FROM Users WHERE ke=? AND details NOT LIKE ?',[req.body.key,'%"sub"%'],function(err,r) { + s.knexQuery({ + action: "select", + columns: "*", + table: "Users", + where: [ + ['ke','=',req.body.key], + ['details','NOT LIKE','%"sub"%'], + ], + },(err,r) => { if(r&&r[0]){ r=r[0] r.details=JSON.parse(r.details) @@ -449,7 +533,7 @@ module.exports = function(s,config,lang,app,io){ if(!user.uid){ user.uid=s.gid() } - req.resp={ + req.resp = { ke:req.body.key, uid:user.uid, auth:s.createHash(s.gid()), @@ -462,12 +546,16 @@ module.exports = function(s,config,lang,app,io){ filter: {} }) } - user.post=[] - Object.keys(req.resp).forEach(function(v){ - user.post.push(req.resp[v]) - }) s.userLog({ke:req.body.key,mid:'$USER'},{type:r.lang['LDAP Success'],msg:{user:user}}) - s.sqlQuery('SELECT * FROM Users WHERE ke=? AND mail=?',[req.body.key,user.cn],function(err,rr){ + s.knexQuery({ + action: "select", + columns: "*", + table: "Users", + where: [ + ['ke','=',req.body.key], + ['mail','=',user.cn], + ], + },function(err,rr) { if(rr&&rr[0]){ //already registered rr=rr[0] @@ -475,12 +563,26 @@ module.exports = function(s,config,lang,app,io){ rr.details=JSON.parse(rr.details) req.resp.lang=s.getLanguageFile(rr.details.lang) s.userLog({ke:req.body.key,mid:'$USER'},{type:r.lang['LDAP User Authenticated'],msg:{user:user,shinobiUID:rr.uid}}) - s.sqlQuery("UPDATE Users SET auth=? WHERE ke=? AND uid=?",[req.resp.auth,req.resp.ke,rr.uid]) + s.knexQuery({ + action: "update", + table: "Users", + update: { + auth: req.resp.auth + }, + where: [ + ['ke','=',req.resp.ke], + ['uid','=',rr.uid], + ] + }) }else{ //new ldap login s.userLog({ke:req.body.key,mid:'$USER'},{type:r.lang['LDAP User is New'],msg:{info:r.lang['Creating New Account'],user:user}}) req.resp.lang=r.lang - s.sqlQuery('INSERT INTO Users (ke,uid,auth,mail,pass,details) VALUES (?,?,?,?,?,?)',user.post) + s.knexQuery({ + action: "insert", + table: "Users", + insert: req.resp, + }) } req.resp.details = JSON.stringify(req.resp.details) req.resp.auth_token = req.resp.auth @@ -516,7 +618,16 @@ module.exports = function(s,config,lang,app,io){ users: true, md5: true },function(data){ - s.sqlQuery('SELECT * FROM Logs WHERE ke=? ORDER BY `time` DESC LIMIT 30',['$'],function(err,r) { + s.knexQuery({ + action: "select", + columns: "*", + table: "Logs", + where: [ + ['ke','=','$'], + ], + orderBy: ['time','desc'], + limit: 30 + },(err,r) => { if(!r){ r=[] } @@ -548,7 +659,17 @@ module.exports = function(s,config,lang,app,io){ } if(!req.details.acceptedMachines[req.body.machineID]){ req.details.acceptedMachines[req.body.machineID]={} - s.sqlQuery("UPDATE Users SET details=? WHERE ke=? AND uid=?",[s.prettyPrint(req.details),req.body.ke,req.body.id]) + s.knexQuery({ + action: "update", + table: "Users", + update: { + details: s.prettyPrint(req.details) + }, + where: [ + ['ke','=',req.body.ke], + ['uid','=',req.body.id], + ] + }) } } req.body.function = s.factorAuth[req.body.ke][req.body.id].function @@ -588,115 +709,115 @@ module.exports = function(s,config,lang,app,io){ res.end(s.prettyPrint({ok:true})) }) }) - /** - * Page : Montage - stand alone squished view with gridstackjs - */ - app.get([ - config.webPaths.apiPrefix+':auth/grid/:ke', - config.webPaths.apiPrefix+':auth/grid/:ke/:group', - config.webPaths.apiPrefix+':auth/cycle/:ke', - config.webPaths.apiPrefix+':auth/cycle/:ke/:group' - ], function(req,res) { - s.auth(req.params,function(user){ - if(user.permissions.get_monitors==="0"){ - res.end(user.lang['Not Permitted']) - return - } - - req.params.protocol=req.protocol; - req.sql='SELECT * FROM Monitors WHERE mode!=? AND mode!=? AND ke=?';req.ar=['stop','idle',req.params.ke]; - if(!req.params.id){ - if(user.details.sub&&user.details.monitors&&user.details.allmonitors!=='1'){ - try{user.details.monitors=JSON.parse(user.details.monitors);}catch(er){} - req.or=[]; - user.details.monitors.forEach(function(v,n){ - req.or.push('mid=?');req.ar.push(v) - }) - req.sql+=' AND ('+req.or.join(' OR ')+')' - } - }else{ - if(!user.details.sub||user.details.allmonitors!=='0'||user.details.monitors.indexOf(req.params.id)>-1){ - req.sql+=' and mid=?';req.ar.push(req.params.id) - }else{ - res.end(user.lang['There are no monitors that you can view with this account.']); - return; - } - } - s.sqlQuery(req.sql,req.ar,function(err,r){ - if(req.params.group){ - var filteredByGroupCheck = {}; - var filteredByGroup = []; - r.forEach(function(v,n){ - var details = JSON.parse(r[n].details); - try{ - req.params.group.split('|').forEach(function(group){ - var groups = JSON.parse(details.groups); - if(groups.indexOf(group) > -1 && !filteredByGroupCheck[v.mid]){ - filteredByGroupCheck[v.mid] = true; - filteredByGroup.push(v) - } - }) - }catch(err){ - - } - }) - r = filteredByGroup; - } - r.forEach(function(v,n){ - if(s.group[v.ke]&&s.group[v.ke].activeMonitors[v.mid]&&s.group[v.ke].activeMonitors[v.mid].watch){ - r[n].currentlyWatching=Object.keys(s.group[v.ke].activeMonitors[v.mid].watch).length - } - r[n].subStream={} - var details = JSON.parse(r[n].details) - if(details.snap==='1'){ - r[n].subStream.jpeg = '/'+req.params.auth+'/jpeg/'+v.ke+'/'+v.mid+'/s.jpg' - } - if(details.stream_channels&&details.stream_channels!==''){ - try{ - details.stream_channels=JSON.parse(details.stream_channels) - r[n].channels=[] - details.stream_channels.forEach(function(b,m){ - var streamURL - switch(b.stream_type){ - case'mjpeg': - streamURL='/'+req.params.auth+'/mjpeg/'+v.ke+'/'+v.mid+'/'+m - break; - case'hls': - streamURL='/'+req.params.auth+'/hls/'+v.ke+'/'+v.mid+'/'+m+'/s.m3u8' - break; - case'h264': - streamURL='/'+req.params.auth+'/h264/'+v.ke+'/'+v.mid+'/'+m - break; - case'flv': - streamURL='/'+req.params.auth+'/flv/'+v.ke+'/'+v.mid+'/'+m+'/s.flv' - break; - case'mp4': - streamURL='/'+req.params.auth+'/mp4/'+v.ke+'/'+v.mid+'/'+m+'/s.mp4' - break; - } - r[n].channels.push(streamURL) - }) - }catch(err){ - s.userLog(req.params,{type:'Broken Monitor Object',msg:'Stream Channels Field is damaged. Skipping.'}) - } - } - }) - var page = config.renderPaths.grid - if(req.path.indexOf('/cycle/') > -1){ - page = config.renderPaths.cycle - } - s.renderPage(req,res,page,{ - data:Object.assign(req.params,req.query), - baseUrl:req.protocol+'://'+req.hostname, - config: s.getConfigWithBranding(req.hostname), - lang:user.lang, - $user:user, - monitors:r, - query:req.query - }); - }) - },res,req) - }); + // /** + // * Page : Montage - stand alone squished view with gridstackjs + // */ + // app.get([ + // config.webPaths.apiPrefix+':auth/grid/:ke', + // config.webPaths.apiPrefix+':auth/grid/:ke/:group', + // config.webPaths.apiPrefix+':auth/cycle/:ke', + // config.webPaths.apiPrefix+':auth/cycle/:ke/:group' + // ], function(req,res) { + // s.auth(req.params,function(user){ + // if(user.permissions.get_monitors==="0"){ + // res.end(user.lang['Not Permitted']) + // return + // } + // + // req.params.protocol=req.protocol; + // req.sql='SELECT * FROM Monitors WHERE mode!=? AND mode!=? AND ke=?';req.ar=['stop','idle',req.params.ke]; + // if(!req.params.id){ + // if(user.details.sub&&user.details.monitors&&user.details.allmonitors!=='1'){ + // try{user.details.monitors=JSON.parse(user.details.monitors);}catch(er){} + // req.or=[]; + // user.details.monitors.forEach(function(v,n){ + // req.or.push('mid=?');req.ar.push(v) + // }) + // req.sql+=' AND ('+req.or.join(' OR ')+')' + // } + // }else{ + // if(!user.details.sub||user.details.allmonitors!=='0'||user.details.monitors.indexOf(req.params.id)>-1){ + // req.sql+=' and mid=?';req.ar.push(req.params.id) + // }else{ + // res.end(user.lang['There are no monitors that you can view with this account.']); + // return; + // } + // } + // s.sqlQuery(req.sql,req.ar,function(err,r){ + // if(req.params.group){ + // var filteredByGroupCheck = {}; + // var filteredByGroup = []; + // r.forEach(function(v,n){ + // var details = JSON.parse(r[n].details); + // try{ + // req.params.group.split('|').forEach(function(group){ + // var groups = JSON.parse(details.groups); + // if(groups.indexOf(group) > -1 && !filteredByGroupCheck[v.mid]){ + // filteredByGroupCheck[v.mid] = true; + // filteredByGroup.push(v) + // } + // }) + // }catch(err){ + // + // } + // }) + // r = filteredByGroup; + // } + // r.forEach(function(v,n){ + // if(s.group[v.ke]&&s.group[v.ke].activeMonitors[v.mid]&&s.group[v.ke].activeMonitors[v.mid].watch){ + // r[n].currentlyWatching=Object.keys(s.group[v.ke].activeMonitors[v.mid].watch).length + // } + // r[n].subStream={} + // var details = JSON.parse(r[n].details) + // if(details.snap==='1'){ + // r[n].subStream.jpeg = '/'+req.params.auth+'/jpeg/'+v.ke+'/'+v.mid+'/s.jpg' + // } + // if(details.stream_channels&&details.stream_channels!==''){ + // try{ + // details.stream_channels=JSON.parse(details.stream_channels) + // r[n].channels=[] + // details.stream_channels.forEach(function(b,m){ + // var streamURL + // switch(b.stream_type){ + // case'mjpeg': + // streamURL='/'+req.params.auth+'/mjpeg/'+v.ke+'/'+v.mid+'/'+m + // break; + // case'hls': + // streamURL='/'+req.params.auth+'/hls/'+v.ke+'/'+v.mid+'/'+m+'/s.m3u8' + // break; + // case'h264': + // streamURL='/'+req.params.auth+'/h264/'+v.ke+'/'+v.mid+'/'+m + // break; + // case'flv': + // streamURL='/'+req.params.auth+'/flv/'+v.ke+'/'+v.mid+'/'+m+'/s.flv' + // break; + // case'mp4': + // streamURL='/'+req.params.auth+'/mp4/'+v.ke+'/'+v.mid+'/'+m+'/s.mp4' + // break; + // } + // r[n].channels.push(streamURL) + // }) + // }catch(err){ + // s.userLog(req.params,{type:'Broken Monitor Object',msg:'Stream Channels Field is damaged. Skipping.'}) + // } + // } + // }) + // var page = config.renderPaths.grid + // if(req.path.indexOf('/cycle/') > -1){ + // page = config.renderPaths.cycle + // } + // s.renderPage(req,res,page,{ + // data:Object.assign(req.params,req.query), + // baseUrl:req.protocol+'://'+req.hostname, + // config: s.getConfigWithBranding(req.hostname), + // lang:user.lang, + // $user:user, + // monitors:r, + // query:req.query + // }); + // }) + // },res,req) + // }); /** * API : Get TV Channels (Monitor Streams) json */ @@ -707,62 +828,49 @@ module.exports = function(s,config,lang,app,io){ req.params.password = req.query.password } var output = ['h264','hls','mp4'] - if(req.query.output&&req.query.output!==''){ + if( + req.query.output && + req.query.output !== '' + ){ output = req.query.output.split(',') output.forEach(function(type,n){ - if(type==='ts'){ - output[n]='h264' - if(output.indexOf('hls')===-1){ + if(type === 'ts'){ + output[n] = 'h264' + if(output.indexOf('hls') === -1){ output.push('hls') } } }) } - var isM3u8 = false; - if(req.query.type==='m3u8'||req.query.type==='m3u_plus'){ - //is m3u8 - isM3u8 = true; - }else{ - res.setHeader('Content-Type', 'application/json'); - } - req.fn=function(user){ + const isM3u8 = req.query.type === 'm3u8' || req.query.type === 'm3u_plus' + s.auth(req.params,function(user){ if(user.permissions.get_monitors==="0"){ res.end(s.prettyPrint([])) return } - if(!req.params.ke){ - req.params.ke = user.ke; - } - if(req.query.id&&!req.params.id){ - req.params.id = req.query.id; - } - req.sql='SELECT * FROM Monitors WHERE mode!=? AND ke=?';req.ar=['stop',req.params.ke]; - if(!req.params.id){ - if(user.details.sub&&user.details.monitors&&user.details.allmonitors!=='1'){ - try{user.details.monitors=JSON.parse(user.details.monitors);}catch(er){} - req.or=[]; - user.details.monitors.forEach(function(v,n){ - req.or.push('mid=?');req.ar.push(v) - }) - req.sql+=' AND ('+req.or.join(' OR ')+')' - } - }else{ - if(!user.details.sub||user.details.allmonitors!=='0'||user.details.monitors.indexOf(req.params.id)>-1){ - req.sql+=' and mid=?';req.ar.push(req.params.id) - }else{ - res.end('[]'); - return; - } - } - s.sqlQuery(req.sql,req.ar,function(err,r){ + const groupKey = user.ke + const monitorId = req.params.id + const monitorRestrictions = s.getMonitorRestrictions(user.details,monitorId) + s.knexQuery({ + action: "select", + columns: "*", + table: "Monitors", + where: [ + ['ke','=',groupKey], + ['mode','!=','stop'], + [ + monitorRestrictions + ] + ] + },(err,r) => { var tvChannelMonitors = []; r.forEach(function(v,n){ var buildStreamURL = function(channelRow,type,channelNumber){ var streamURL - if(req.query.streamtype && req.query.streamtype != type){ - return - } - if(channelNumber){channelNumber = '/'+channelNumber}else{channelNumber=''} + if(req.query.streamtype && req.query.streamtype != type){ + return + } + if(channelNumber){channelNumber = '/' + channelNumber}else{channelNumber = ''} switch(type){ case'mjpeg': streamURL='/'+req.params.auth+'/mjpeg/'+v.ke+'/'+v.mid+channelNumber @@ -819,7 +927,7 @@ module.exports = function(s,config,lang,app,io){ tvChannelMonitors.forEach(function(channelRow,n){ output.forEach(function(type){ if(channelRow.streamsSortedByType[type]){ - if(req.query.type==='m3u_plus'){ + if(req.query.type === 'm3u_plus'){ m3u8 +='#EXTINF-1 tvg-id="'+channelRow.mid+'" tvg-name="'+channelRow.channel+'" tvg-logo="'+req.protocol+'://'+req.headers.host+channelRow.snapshot+'" group-title="'+channelRow.groupTitle+'",'+channelRow.channel+'\n' }else{ m3u8 +='#EXTINF:-1,'+channelRow.channel+' ('+type.toUpperCase()+') \n' @@ -830,12 +938,11 @@ module.exports = function(s,config,lang,app,io){ }) res.end(m3u8) }else{ - if(tvChannelMonitors.length===1){tvChannelMonitors=tvChannelMonitors[0];} - res.end(s.prettyPrint(tvChannelMonitors)); + if(tvChannelMonitors.length === 1)tvChannelMonitors=tvChannelMonitors[0]; + s.closeJsonResponse(res,tvChannelMonitors) } }) - } - s.auth(req.params,req.fn,res,req); + },res,req); }); /** * API : Get Monitors @@ -843,30 +950,25 @@ module.exports = function(s,config,lang,app,io){ app.get([config.webPaths.apiPrefix+':auth/monitor/:ke',config.webPaths.apiPrefix+':auth/monitor/:ke/:id'], function (req,res){ req.ret={ok:false}; res.setHeader('Content-Type', 'application/json'); - req.fn=function(user){ - if(user.permissions.get_monitors==="0"){ - res.end(s.prettyPrint([])) - return - } - req.sql='SELECT * FROM Monitors WHERE ke=?';req.ar=[req.params.ke]; - if(!req.params.id){ - if(user.details.sub&&user.details.monitors&&user.details.allmonitors!=='1'){ - try{user.details.monitors=JSON.parse(user.details.monitors);}catch(er){} - req.or=[]; - user.details.monitors.forEach(function(v,n){ - req.or.push('mid=?');req.ar.push(v) - }) - req.sql+=' AND ('+req.or.join(' OR ')+')' - } - }else{ - if(!user.details.sub||user.details.allmonitors!=='0'||user.details.monitors.indexOf(req.params.id)>-1){ - req.sql+=' and mid=?';req.ar.push(req.params.id) - }else{ - res.end('[]'); - return; - } + s.auth(req.params,(user){ + if(user.permissions.get_monitors==="0"){ + res.end(s.prettyPrint([])) + return } - s.sqlQuery(req.sql,req.ar,function(err,r){ + const groupKey = user.ke + const monitorId = req.params.id + const monitorRestrictions = s.getMonitorRestrictions(user.details,monitorId) + s.knexQuery({ + action: "select", + columns: "*", + table: "Monitors", + where: [ + ['ke','=',groupKey], + [ + monitorRestrictions + ] + ] + },(err,r) => { r.forEach(function(v,n){ if(s.group[v.ke] && s.group[v.ke].activeMonitors[v.mid]){ r[n].currentlyWatching = Object.keys(s.group[v.ke].activeMonitors[v.mid].watch).length @@ -920,8 +1022,7 @@ module.exports = function(s,config,lang,app,io){ if(r.length===1){r=r[0];} res.end(s.prettyPrint(r)); }) - } - s.auth(req.params,req.fn,res,req); + },res,req); }); /** * API : Merge Recorded Videos into one file @@ -934,21 +1035,31 @@ module.exports = function(s,config,lang,app,io){ if(req.query.videos && req.query.videos !== ''){ s.auth(req.params,function(user){ var videosSelected = JSON.parse(req.query.videos) - var where = [] - var values = [] + const whereQuery = [] + var didOne = false videosSelected.forEach(function(video){ - where.push("(ke=? AND mid=? AND `time`=?)") - if(!video.ke)video.ke = req.params.ke - values.push(video.ke) - values.push(video.mid) var time = s.nameToTime(video.filename) if(req.query.isUTC === 'true'){ time = s.utcToLocal(time) } - time = new Date(time) - values.push(time) + if(didOne){ + whereQuery.push(['or','ke','=',req.params.ke]) + }else{ + didOne = false + whereQuery.push(['ke','=',req.params.ke]) + } + whereQuery.push( + ['mid','=',video.mid], + ['time','=',time], + ) + }) - s.sqlQuery('SELECT * FROM Videos WHERE '+where.join(' OR '),values,function(err,r){ + s.knexQuery({ + action: "select", + columns: "*", + table: "Videos", + where: whereQuery + },(err,r) => { var resp = {ok: false} if(r && r[0]){ s.mergeRecordedVideos(r,req.params.ke,function(fullPath,filename){ @@ -1014,6 +1125,7 @@ module.exports = function(s,config,lang,app,io){ (!userDetails.video_view || userDetails.video_view.indexOf(monitorId)===-1) ) },(response) => { + console.log(response) s.buildVideoLinks(response.videos,{ auth : req.params.auth, videoParam : videoParam, @@ -1105,35 +1217,38 @@ module.exports = function(s,config,lang,app,io){ app.get(config.webPaths.apiPrefix+':auth/smonitor/:ke', function (req,res){ req.ret={ok:false}; res.setHeader('Content-Type', 'application/json'); - req.fn=function(user){ + s.auth(req.params,(user) => { if(user.permissions.get_monitors==="0"){ res.end(s.prettyPrint([])) return } - req.sql='SELECT * FROM Monitors WHERE ke=?';req.ar=[req.params.ke]; - if(user.details.sub&&user.details.monitors&&user.details.allmonitors!=='1'){ - try{user.details.monitors=JSON.parse(user.details.monitors);}catch(er){} - req.or=[]; - user.details.monitors.forEach(function(v,n){ - req.or.push('mid=?');req.ar.push(v) + const groupKey = user.ke + const monitorId = req.params.id + const monitorRestrictions = s.getMonitorRestrictions(user.details,monitorId) + s.knexQuery({ + action: "select", + columns: "*", + table: "Monitors", + where: [ + ['ke','=',groupKey], + [ + monitorRestrictions + ] + ] + },(err,r) => { + const startedMonitors = [] + r.forEach(function(v){ + if( + s.group[groupKey] && + s.group[groupKey].activeMonitors[v.mid] && + s.group[groupKey].activeMonitors[v.mid].isStarted === true + ){ + startedMonitors.push(v) + } }) - req.sql+=' AND ('+req.or.join(' OR ')+')' - } - s.sqlQuery(req.sql,req.ar,function(err,r){ - if(r&&r[0]){ - req.ar=[]; - r.forEach(function(v){ - if(s.group[req.params.ke]&&s.group[req.params.ke].activeMonitors[v.mid]&&s.group[req.params.ke].activeMonitors[v.mid].isStarted === true){ - req.ar.push(v) - } - }) - }else{ - req.ar=[]; - } - res.end(s.prettyPrint(req.ar)); + s.closeJsonResponse(res,startedMonitors) }) - } - s.auth(req.params,req.fn,res,req); + },res,req); }); /** * API : Monitor Mode Controller @@ -1152,9 +1267,18 @@ module.exports = function(s,config,lang,app,io){ 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){ - if(r&&r[0]){ - r=r[0]; + s.knexQuery({ + action: "select", + columns: "*", + table: "Monitors", + where: [ + ['ke','=',req.params.ke], + ['mid','=',req.params.id], + ], + limit: 1 + },(err,r) => { + if(r && r[0]){ + r = r[0]; if(req.query.reset==='1'||(s.group[r.ke]&&s.group[r.ke].rawMonitorConfigurations[r.mid].mode!==req.params.f)||req.query.fps&&(!s.group[r.ke].activeMonitors[r.mid].currentState||!s.group[r.ke].activeMonitors[r.mid].currentState.trigger_on)){ if(req.query.reset!=='1'||!s.group[r.ke].activeMonitors[r.mid].trigger_timer){ if(!s.group[r.ke].activeMonitors[r.mid].currentState)s.group[r.ke].activeMonitors[r.mid].currentState={} @@ -1172,7 +1296,17 @@ module.exports = function(s,config,lang,app,io){ s.group[r.ke].activeMonitors[r.mid].currentState.detector_trigger_record_fps=r.fps } r.id=r.mid; - s.sqlQuery('UPDATE Monitors SET mode=? WHERE ke=? AND mid=?',[r.mode,r.ke,r.mid]); + s.knexQuery({ + action: "update", + table: "Monitors", + update: { + mode: r.mode + }, + where: [ + ['ke','=',r.ke], + ['mid','=',r.mid], + ] + }) s.group[r.ke].rawMonitorConfigurations[r.mid]=r; s.tx({f:'monitor_edit',mid:r.mid,ke:r.ke,mon:r},'GRP_'+r.ke); s.tx({f:'monitor_edit',mid:r.mid,ke:r.ke,mon:r},'STR_'+r.ke); @@ -1205,7 +1339,17 @@ module.exports = function(s,config,lang,app,io){ } s.group[r.ke].activeMonitors[r.mid].trigger_timer=setTimeout(function(){ delete(s.group[r.ke].activeMonitors[r.mid].trigger_timer) - s.sqlQuery('UPDATE Monitors SET mode=? WHERE ke=? AND mid=?',[s.group[r.ke].activeMonitors[r.mid].currentState.mode,r.ke,r.mid]); + s.knexQuery({ + action: "update", + table: "Monitors", + update: { + mode: s.group[r.ke].activeMonitors[r.mid].currentState.mode + }, + where: [ + ['ke','=',r.ke], + ['mid','=',r.mid], + ] + }) r.neglectTriggerTimer=1; r.mode=s.group[r.ke].activeMonitors[r.mid].currentState.mode; r.fps=s.group[r.ke].activeMonitors[r.mid].currentState.fps; @@ -1231,37 +1375,32 @@ module.exports = function(s,config,lang,app,io){ },res,req); }) /** - * API : Get fileBin files + * API : Get fileBin file rows */ app.get([config.webPaths.apiPrefix+':auth/fileBin/:ke',config.webPaths.apiPrefix+':auth/fileBin/:ke/:id'],function (req,res){ res.setHeader('Content-Type', 'application/json'); - req.fn=function(user){ - req.sql='SELECT * FROM Files WHERE ke=?';req.ar=[req.params.ke]; - if(user.details.sub&&user.details.monitors&&user.details.allmonitors!=='1'){ - try{user.details.monitors=JSON.parse(user.details.monitors);}catch(er){} - req.or=[]; - user.details.monitors.forEach(function(v,n){ - req.or.push('mid=?');req.ar.push(v) + s.auth(req.params,(user) => { + const groupKey = user.ke + const monitorId = req.params.id + const monitorRestrictions = s.getMonitorRestrictions(user.details,monitorId) + s.knexQuery({ + action: "select", + columns: "*", + table: "Files", + where: [ + ['ke','=',groupKey], + [ + monitorRestrictions + ] + ] + },(err,r) => { + r.forEach(function(v){ + v.details = JSON.parse(v.details) + v.href='/'+req.params.auth+'/fileBin/'+req.params.ke+'/'+req.params.id+'/'+v.details.year+'/'+v.details.month+'/'+v.details.day+'/'+v.name; }) - req.sql+=' AND ('+req.or.join(' OR ')+')' - }else{ - if(req.params.id&&(!user.details.sub||user.details.allmonitors!=='0'||user.details.monitors.indexOf(req.params.id)>-1)){ - req.sql+=' and mid=?';req.ar.push(req.params.id) - } - } - s.sqlQuery(req.sql,req.ar,function(err,r){ - if(!r){ - r=[] - }else{ - r.forEach(function(v){ - v.details=JSON.parse(v.details) - 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.prettyPrint(r)); + s.closeJsonResponse(res,r) }) - } - s.auth(req.params,req.fn,res,req); + },res,req); }); /** * API : Get fileBin file @@ -1272,11 +1411,26 @@ module.exports = function(s,config,lang,app,io){ res.end(user.lang['File Not Found']) } if (!s.group[req.params.ke].fileBin[req.params.id+'/'+req.params.file]){ - s.sqlQuery('SELECT * FROM Files WHERE ke=? AND mid=? AND name=?',[req.params.ke,req.params.id,req.params.file],function(err,r){ - if(r&&r[0]){ + const groupKey = user.ke + const monitorId = req.params.id + const monitorRestrictions = s.getMonitorRestrictions(user.details,monitorId) + s.knexQuery({ + action: "select", + columns: "*", + table: "Files", + where: [ + ['ke','=',groupKey], + ['mid','=',req.params.id], + ['name','=',req.params.file], + [ + monitorRestrictions + ] + ] + },(err,r) => { + if(r && r[0]){ r = r[0] r.details = JSON.parse(r.details) - req.dir = s.dir.fileBin+req.params.ke+'/'+req.params.id+'/'+r.details.year+'/'+r.details.month+'/'+r.details.day+'/'+req.params.file; + req.dir = s.dir.fileBin + req.params.ke + '/' + req.params.id + '/' + r.details.year + '/' + r.details.month + '/' + r.details.day + '/' + req.params.file; fs.stat(req.dir,function(err,stats){ if(!err){ res.on('finish',function(){res.end()}) @@ -1294,218 +1448,6 @@ module.exports = function(s,config,lang,app,io){ } },res,req); }); - // /** - // * API : Zip Videos and Get Link from fileBin - // */ - // app.get(config.webPaths.apiPrefix+':auth/zipVideos/:ke', function (req,res){ - // var failed = function(resp){ - // res.setHeader('Content-Type', 'application/json'); - // res.end(s.prettyPrint(resp)) - // } - // if(req.query.videos && req.query.videos !== ''){ - // s.auth(req.params,function(user){ - // var videosSelected = JSON.parse(req.query.videos) - // var where = [] - // var values = [] - // videosSelected.forEach(function(video){ - // where.push("(ke=? AND mid=? AND `time`=?)") - // if(!video.ke)video.ke = req.params.ke - // values.push(video.ke) - // values.push(video.mid) - // var time = s.nameToTime(video.filename) - // if(req.query.isUTC === 'true'){ - // time = s.utcToLocal(time) - // } - // time = new Date(time) - // values.push(time) - // }) - // s.sqlQuery('SELECT * FROM Videos WHERE '+where.join(' OR '),values,function(err,r){ - // var resp = {ok: false} - // if(r && r[0]){ - // resp.ok = true - // var zipDownload = null - // var tempFiles = [] - // var fileId = s.gid() - // var fileBinDir = s.dir.fileBin+req.params.ke+'/' - // var tempScript = s.dir.streams+req.params.ke+'/'+fileId+'.sh' - // var zippedFilename = s.formattedTime()+'-'+fileId+'-Shinobi_Recordings.zip' - // var zippedFile = fileBinDir+zippedFilename - // var script = 'cd '+fileBinDir+' && zip -9 -r '+zippedFile - // res.on('close', () => { - // if(zipDownload && zipDownload.destroy){ - // zipDownload.destroy() - // } - // fs.unlink(zippedFile); - // }) - // fs.mkdir(fileBinDir,function(err){ - // s.handleFolderError(err) - // r.forEach(function(video){ - // var timeFormatted = s.formattedTime(video.time) - // video.filename = timeFormatted+'.'+video.ext - // var dir = s.getVideoDirectory(video)+video.filename - // var tempVideoFile = timeFormatted+' - '+video.mid+'.'+video.ext - // fs.writeFileSync(fileBinDir+tempVideoFile, fs.readFileSync(dir)) - // tempFiles.push(fileBinDir+tempVideoFile) - // script += ' "'+tempVideoFile+'"' - // }) - // fs.writeFileSync(tempScript,script,'utf8') - // var zipCreate = spawn('sh',(tempScript).split(' '),{detached: true}) - // zipCreate.stderr.on('data',function(data){ - // s.userLog({ke:req.params.ke,mid:'$USER'},{title:'Zip Create Error',msg:data.toString()}) - // }) - // zipCreate.on('exit',function(data){ - // fs.unlinkSync(tempScript) - // tempFiles.forEach(function(file){ - // fs.unlink(file,function(){}) - // }) - // res.setHeader('Content-Disposition', 'attachment; filename="'+zippedFilename+'"') - // var zipDownload = fs.createReadStream(zippedFile) - // zipDownload.pipe(res) - // zipDownload.on('error', function (error) { - // var errorString = error.toString() - // s.userLog({ - // ke: req.params.ke, - // mid: '$USER' - // },{ - // title: 'Zip Download Error', - // msg: errorString - // }) - // if(zipDownload && zipDownload.destroy){ - // zipDownload.destroy() - // } - // res.end(s.prettyPrint({ - // ok: false, - // msg: errorString - // })) - // }) - // zipDownload.on('close', function () { - // res.end() - // zipDownload.destroy() - // fs.unlinkSync(zippedFile) - // }) - // }) - // }) - // }else{ - // failed({ok:false,msg:'No Videos Found'}) - // } - // }) - // },res,req); - // }else{ - // failed({ok:false,msg:'"videos" query variable is missing from request.'}) - // } - // }) - // /** - // * API : Zip Cloud Videos and Get Link from fileBin - // */ - // app.get(config.webPaths.apiPrefix+':auth/zipCloudVideos/:ke', function (req,res){ - // var failed = function(resp){ - // res.setHeader('Content-Type', 'application/json'); - // res.end(s.prettyPrint(resp)) - // } - // if(req.query.videos && req.query.videos !== ''){ - // s.auth(req.params,function(user){ - // var videosSelected = JSON.parse(req.query.videos) - // var where = [] - // var values = [] - // videosSelected.forEach(function(video){ - // where.push("(ke=? AND mid=? AND `time`=?)") - // if(!video.ke)video.ke = req.params.ke - // values.push(video.ke) - // values.push(video.mid) - // var time = s.nameToTime(video.filename) - // if(req.query.isUTC === 'true'){ - // time = s.utcToLocal(time) - // } - // time = new Date(time) - // values.push(time) - // }) - // s.sqlQuery('SELECT * FROM `Cloud Videos` WHERE '+where.join(' OR '),values,function(err,r){ - // var resp = {ok: false} - // if(r && r[0]){ - // resp.ok = true - // var zipDownload = null - // var tempFiles = [] - // var fileId = s.gid() - // var fileBinDir = s.dir.fileBin+req.params.ke+'/' - // var tempScript = s.dir.streams+req.params.ke+'/'+fileId+'.sh' - // var zippedFilename = s.formattedTime()+'-'+fileId+'-Shinobi_Cloud_Backed_Recordings.zip' - // var zippedFile = fileBinDir+zippedFilename - // var script = 'cd '+fileBinDir+' && zip -9 -r '+zippedFile - // res.on('close', () => { - // if(zipDownload && zipDownload.destroy){ - // zipDownload.destroy() - // } - // fs.unlink(zippedFile); - // }) - // fs.mkdir(fileBinDir,function(err){ - // var cloudDownloadCount = 0 - // var getFile = function(video,completed){ - // if(!video)completed(); - // s.checkDetails(video) - // var filename = video.href.split('/') - // filename = filename[filename.length - 1] - // var timeFormatted = s.formattedTime(video.time) - // var tempVideoFile = video.details.type + '-' + video.mid + '-' + filename - // var tempFileWriteStream = fs.createWriteStream(fileBinDir+tempVideoFile) - // tempFileWriteStream.on('finish', function() { - // ++cloudDownloadCount - // getFile(r[cloudDownloadCount],completed) - // }) - // var cloudVideoDownload = request(video.href) - // cloudVideoDownload.on('response', function (res) { - // res.pipe(tempFileWriteStream) - // }) - // tempFiles.push(fileBinDir+tempVideoFile) - // script += ' "'+tempVideoFile+'"' - // } - // getFile(r[cloudDownloadCount],function(){ - // fs.writeFileSync(tempScript,script,'utf8') - // var zipCreate = spawn('sh',(tempScript).split(' '),{detached: true}) - // zipCreate.stderr.on('data',function(data){ - // s.userLog({ke:req.params.ke,mid:'$USER'},{title:'Zip Create Error',msg:data.toString()}) - // }) - // zipCreate.on('exit',function(data){ - // fs.unlinkSync(tempScript) - // tempFiles.forEach(function(file){ - // fs.unlink(file,function(){}) - // }) - // res.setHeader('Content-Disposition', 'attachment; filename="' + zippedFilename + '"') - // var zipDownload = fs.createReadStream(zippedFile) - // zipDownload.pipe(res) - // zipDownload.on('error', function (error) { - // var errorString = error.toString() - // s.userLog({ - // ke: req.params.ke, - // mid: '$USER' - // },{ - // title: 'Zip Download Error', - // msg: errorString - // }) - // if(zipDownload && zipDownload.destroy){ - // zipDownload.destroy() - // } - // res.end(s.prettyPrint({ - // ok: false, - // msg: errorString - // })) - // }) - // zipDownload.on('close', function () { - // res.end() - // zipDownload.destroy() - // fs.unlinkSync(zippedFile) - // }) - // }) - // }) - // }) - // }else{ - // failed({ok:false,msg:'No Videos Found'}) - // } - // }) - // },res,req); - // }else{ - // failed({ok:false,msg:'"videos" query variable is missing from request.'}) - // } - // }) /** * API : Get Cloud Video File (proxy) */ @@ -1520,7 +1462,19 @@ module.exports = function(s,config,lang,app,io){ time = s.utcToLocal(time) } time = new Date(time) - s.sqlQuery('SELECT * FROM `Cloud Videos` WHERE ke=? AND mid=? AND `time`=? LIMIT 1',[req.params.ke,req.params.id,time],function(err,r){ + const groupKey = user.ke + const monitorId = req.params.id + s.knexQuery({ + action: "select", + columns: "*", + table: "Cloud Videos", + where: [ + ['ke','=',groupKey], + ['mid','=',req.params.id], + ['time','=',time] + ], + limit: 1 + },(err,r) => { if(r&&r[0]){ r = r[0] if(JSON.parse(r.details).type === 'googd' && s.cloudDiskUseOnGetVideoDataExtensions['googd']){ @@ -1553,7 +1507,19 @@ module.exports = function(s,config,lang,app,io){ time = s.utcToLocal(time) } time = new Date(time) - s.sqlQuery('SELECT * FROM Videos WHERE ke=? AND mid=? AND `time`=? LIMIT 1',[req.params.ke,req.params.id,time],function(err,r){ + const groupKey = user.ke + const monitorId = req.params.id + s.knexQuery({ + action: "select", + columns: "*", + table: "Videos", + where: [ + ['ke','=',groupKey], + ['mid','=',req.params.id], + ['time','=',time] + ], + limit: 1 + },(err,r) => { if(r&&r[0]){ req.dir=s.getVideoDirectory(r[0])+req.params.file fs.stat(req.dir,function(err,stats){ @@ -1728,7 +1694,7 @@ module.exports = function(s,config,lang,app,io){ * API : Upload Video File * API : Add "streamIn" query string to Push to "Dashcam (Streamer v2)" FFMPEG Process */ - app.post(config.webPaths.apiPrefix+':auth/videos/:ke/:id',fileupload(), async (req,res) => { + app.post(config.webPaths.apiPrefix+':auth/videos/:ke/:id',fileupload(), (req,res) => { var response = {ok:false} res.setHeader('Content-Type', 'application/json'); s.auth(req.params,function(user){ @@ -1738,86 +1704,79 @@ module.exports = function(s,config,lang,app,io){ } var groupKey = req.params.ke var monitorId = req.params.id - var origURL = req.originalUrl.split('/') - var videoParam = origURL[origURL.indexOf(req.params.auth) + 1] - var videoSet = 'Videos' - req.sql='SELECT * FROM `Monitors` WHERE ke=? AND mid=?'; - req.ar=[groupKey,monitorId]; - s.sqlQuery(req.sql,req.ar,function(err,r){ - if(r && r[0]){ - var monitor = r[0] - // req.query.overwrite === '1' - if(s.group[groupKey] && s.group[groupKey].activeMonitors[monitorId]){ - try { - if(!req.files) { - res.send({ - status: false, - message: 'No file uploaded' - }); - } else { - let video = req.files.video; - if(req.query.streamIn === '1'){ - var tempLocation = s.getStreamsDirectory(monitor) + video.name; - video.mv(tempLocation,function(){ - var fileStream = fs.createReadStream(tempLocation) - fileStream.on('close',function(){ - - }) - fileStream.on('data',function(data){ - try{ - s.group[groupKey].activeMonitors[monitorId].spawn.stdin.write(data); - }catch(err){ - console.log(err) - } - }) - // s.group[groupKey].activeMonitors[monitorId].spawn.stdin.write(fs.readFileSync(tempLocation,'binary')); - res.end(s.prettyPrint({ - ok: true, - message: 'File is transcoding', - data: { - name: video.name, - mimetype: video.mimetype, - size: video.size - } - })) - }); - }else{ - var time = new Date(parseInt(video.name.split('.')[0])) - var filename = s.formattedTime(time) + '.' + monitor.ext - video.mv(s.getVideoDirectory(monitor) + filename,function(){ - s.insertCompletedVideo(monitor,{ - file: filename, - events: s.group[groupKey].activeMonitors[monitorId].detector_motion_count, - endTime: req.body.endTime.indexOf('-') > -1 ? s.nameToTime(req.body.endTime) : parseInt(req.body.endTime) || null, - },function(){ - response.ok = true - response.filename = filename - res.end(s.prettyPrint({ - ok: true, - message: 'File is uploaded', - data: { - name: video.name, - mimetype: video.mimetype, - size: video.size - } - })) - }) - }); - } - } - } catch (err) { - response.err = err - res.status(500).end(response) + // req.query.overwrite === '1' + if(s.group[groupKey] && s.group[groupKey].activeMonitors && s.group[groupKey].activeMonitors[monitorId]){ + var monitor = s.group[groupKey].rawMonitorConfigurations[monitorId] + try { + if(!req.files) { + res.send({ + status: false, + message: 'No file uploaded' + }); + } else { + let video = req.files.video; + console.log('come here 1') + if(req.query.streamIn === '1'){ + console.log('come here 2',video.name) + var tempLocation = s.getStreamsDirectory(monitor) + video.name; + console.log('come here 3',tempLocation) + video.mv(tempLocation,function(){ + console.log('come here 4') + // var fileStream = fs.createReadStream(tempLocation) + // fileStream.on('close',function(){ + // s.file('delete',tempLocation) + // }) + // fileStream.on('data',function(data){ + // try{ + // // s.group[groupKey].activeMonitors[monitorId].spawn.stdin.write(data); + // }catch(err){ + // console.log(err) + // } + // }) + s.group[groupKey].activeMonitors[monitorId].spawn.stdin.write(fs.readFileSync(tempLocation,'binary')); + s.file('delete',tempLocation) + res.end(s.prettyPrint({ + ok: true, + message: 'File is transcoding', + data: { + name: video.name, + mimetype: video.mimetype, + size: video.size + } + })) + }); + }else{ + var time = new Date(parseInt(video.name.split('.')[0])) + var filename = s.formattedTime(time) + '.' + monitor.ext + video.mv(s.getVideoDirectory(monitor) + filename,function(){ + s.insertCompletedVideo(monitor,{ + file: filename, + events: s.group[groupKey].activeMonitors[monitorId].detector_motion_count, + endTime: req.body.endTime.indexOf('-') > -1 ? s.nameToTime(req.body.endTime) : parseInt(req.body.endTime) || null, + },function(){ + response.ok = true + response.filename = filename + res.end(s.prettyPrint({ + ok: true, + message: 'File is uploaded', + data: { + name: video.name, + mimetype: video.mimetype, + size: video.size + } + })) + }) + }); } - }else{ - response.error = 'Non Existant Monitor' - res.end(s.prettyPrint(response)) } - }else{ - response.msg = user.lang['No such file'] - res.end(s.prettyPrint(response)) + } catch (err) { + response.err = err + res.status(500).end(response) } - }) + }else{ + response.error = 'Non Existant Monitor' + res.end(s.prettyPrint(response)) + } },res,req); }) /** @@ -1849,10 +1808,20 @@ module.exports = function(s,config,lang,app,io){ videoSet = 'Cloud Videos' break; } - req.sql='SELECT * FROM `'+videoSet+'` WHERE ke=? AND mid=? AND `time`=?'; - req.ar=[req.params.ke,req.params.id,time]; - s.sqlQuery(req.sql,req.ar,function(err,r){ - if(r&&r[0]){ + const groupKey = user.ke + const monitorId = req.params.id + s.knexQuery({ + action: "select", + columns: "*", + table: videoSet, + where: [ + ['ke','=',groupKey], + ['mid','=',req.params.id], + ['time','=',time] + ], + limit: 1 + },(err,r) => { + if(r && r[0]){ r=r[0];r.filename=s.formattedTime(r.time)+'.'+r.ext; switch(req.params.mode){ case'fix': @@ -1871,7 +1840,18 @@ module.exports = function(s,config,lang,app,io){ req.ret.msg='Not a valid value.'; }else{ req.ret.ok=true; - s.sqlQuery('UPDATE `'+videoSet+'` SET status=? WHERE ke=? AND mid=? AND `time`=?',[req.params.f,req.params.ke,req.params.id,time]) + s.knexQuery({ + action: "update", + table: videoSet, + update: { + status: req.params.f + }, + where: [ + ['ke','=',groupKey], + ['mid','=',req.params.id], + ['time','=',time] + ] + }) s.tx(r,'GRP_'+r.ke); } break; From b1bb64397af63c4b9cd3d1cfd421aaf91d8c1b14 Mon Sep 17 00:00:00 2001 From: Moe Date: Sat, 11 Jul 2020 14:06:25 -0700 Subject: [PATCH 022/175] sqlQuery Conversion : webServerSuperPaths.js + superApiPrefix fix + minor fixes --- libs/webServerSuperPaths.js | 279 ++++++++++++++++++++---------------- 1 file changed, 155 insertions(+), 124 deletions(-) diff --git a/libs/webServerSuperPaths.js b/libs/webServerSuperPaths.js index eeebf9a3..0e64407c 100644 --- a/libs/webServerSuperPaths.js +++ b/libs/webServerSuperPaths.js @@ -7,62 +7,30 @@ var exec = require('child_process').exec; var spawn = require('child_process').spawn; var execSync = require('child_process').execSync; module.exports = function(s,config,lang,app){ + /** * API : Superuser : Get Logs */ - app.all([config.webPaths.supersuperApiPrefix+':auth/logs'], function (req,res){ + app.all([config.webPaths.superApiPrefix+':auth/logs'], function (req,res){ req.ret={ok:false}; s.superAuth(req.params,function(resp){ - req.sql='SELECT * FROM Logs WHERE ke=?';req.ar=['$']; - if(!req.params.id){ - if(user.details.sub&&user.details.monitors&&user.details.allmonitors!=='1'){ - try{user.details.monitors=JSON.parse(user.details.monitors);}catch(er){} - req.or=[]; - user.details.monitors.forEach(function(v,n){ - req.or.push('mid=?');req.ar.push(v) - }) - req.sql+=' AND ('+req.or.join(' OR ')+')' - } - }else{ - if(!user.details.sub||user.details.allmonitors!=='0'||user.details.monitors.indexOf(req.params.id)>-1||req.params.id.indexOf('$')>-1){ - req.sql+=' and mid=?';req.ar.push(req.params.id) - }else{ - res.end('[]'); - return; - } - } - if(req.query.start||req.query.end){ - if(!req.query.startOperator||req.query.startOperator==''){ - req.query.startOperator='>=' - } - if(!req.query.endOperator||req.query.endOperator==''){ - req.query.endOperator='<=' - } - if(req.query.start && req.query.start !== '' && req.query.end && req.query.end !== ''){ - req.query.start = s.stringToSqlTime(req.query.start) - req.query.end = s.stringToSqlTime(req.query.end) - req.sql+=' AND `time` '+req.query.startOperator+' ? AND `time` '+req.query.endOperator+' ?'; - req.ar.push(req.query.start) - req.ar.push(req.query.end) - }else if(req.query.start && req.query.start !== ''){ - req.query.start = s.stringToSqlTime(req.query.start) - req.sql+=' AND `time` '+req.query.startOperator+' ?'; - req.ar.push(req.query.start) - } - } - if(!req.query.limit||req.query.limit==''){req.query.limit=50} - req.sql+=' ORDER BY `time` DESC LIMIT '+req.query.limit+''; - s.sqlQuery(req.sql,req.ar,function(err,r){ - if(err){ - err.sql=req.sql; - res.end(s.prettyPrint(err)); - return - } - if(!r){r=[]} - r.forEach(function(v,n){ - r[n].info=JSON.parse(v.info) + const monitorRestrictions = s.getMonitorRestrictions(user.details,req.params.id) + s.getDatabaseRows({ + monitorRestrictions: monitorRestrictions, + table: 'Logs', + groupKey: req.params.ke, + date: req.query.date, + startDate: req.query.start, + endDate: req.query.end, + startOperator: req.query.startOperator, + endOperator: req.query.endOperator, + limit: req.query.limit, + archived: req.query.archived, + },(response) => { + response.rows.forEach(function(v,n){ + r[n].info = JSON.parse(v.info) }) - res.end(s.prettyPrint(r)) + s.closeJsonResponse(res,r) }) },res,req) }) @@ -71,11 +39,16 @@ module.exports = function(s,config,lang,app){ */ app.all(config.webPaths.superApiPrefix+':auth/logs/delete', function (req,res){ s.superAuth(req.params,function(resp){ - s.sqlQuery('DELETE FROM Logs WHERE ke=?',['$'],function(){ - var endData = { + s.knexQuery({ + action: "delete", + table: "Logs", + where: [ + ['ke','=','$'], + ] + },() => { + s.closeJsonResponse(res,{ ok : true - } - res.end(s.prettyPrint(endData)) + }) }) },res,req) }) @@ -99,7 +72,7 @@ module.exports = function(s,config,lang,app){ var endData = { ok : true } - res.end(s.prettyPrint(endData)) + s.closeJsonResponse(res,endData) },res,req) }) /** @@ -124,7 +97,7 @@ module.exports = function(s,config,lang,app){ s.systemLog('Flush PM2 Logs',{by:resp.$user.mail,ip:resp.ip}) endData.logsOuput = execSync('pm2 flush') } - res.end(s.prettyPrint(endData)) + s.closeJsonResponse(res,endData) },res,req) }) /** @@ -149,7 +122,7 @@ module.exports = function(s,config,lang,app){ s.tx({f:'save_configuration'},'$') }) } - res.end(s.prettyPrint(endData)) + s.closeJsonResponse(res,endData) },res,req) }) /** @@ -163,22 +136,23 @@ module.exports = function(s,config,lang,app){ var endData = { ok : true } - searchQuery = 'SELECT ke,uid,auth,mail,details FROM Users' - queryVals = [] + const whereQuery = [] switch(req.params.type){ case'admin':case'administrator': - searchQuery += ' WHERE details NOT LIKE ?' - queryVals.push('%"sub"%') + whereQuery.push(['details','NOT LIKE','%"sub"%']) break; case'sub':case'subaccount': - searchQuery += ' WHERE details LIKE ?' - queryVals.push('%"sub"%') + whereQuery.push(['details','LIKE','%"sub"%']) break; } - // ' WHERE details NOT LIKE ?' - s.sqlQuery(searchQuery,queryVals,function(err,users) { + s.knexQuery({ + action: "select", + columns: "ke,uid,auth,mail,details", + table: "Users", + where: whereQuery + },(err,users) => { endData.users = users - res.end(s.prettyPrint(endData)) + s.closeJsonResponse(res,endData) }) },res,req) }) @@ -237,7 +211,7 @@ module.exports = function(s,config,lang,app){ endData.ok = false endData.msg = lang.postDataBroken } - res.end(s.prettyPrint(endData)) + s.closeJsonResponse(res,endData) },res,req) }) /** @@ -249,7 +223,7 @@ module.exports = function(s,config,lang,app){ ok : false } var close = function(){ - res.end(s.prettyPrint(endData)) + s.closeJsonResponse(res,endData) } var isCallbacking = false var form = s.getPostData(req) @@ -257,7 +231,14 @@ module.exports = function(s,config,lang,app){ if(form.mail !== '' && form.pass !== ''){ if(form.pass === form.password_again || form.pass === form.pass_again){ isCallbacking = true - s.sqlQuery('SELECT * FROM Users WHERE mail=?',[form.mail],function(err,r) { + s.knexQuery({ + action: "select", + columns: "*", + table: "Users", + where: [ + ['mail','=',form.mail] + ] + },(err,r) => { if(r&&r[0]){ //found address already exists endData.msg = lang['Email address is in use.']; @@ -277,16 +258,17 @@ module.exports = function(s,config,lang,app){ form.details = JSON.stringify(form.details) } //write user to db - s.sqlQuery( - 'INSERT INTO Users (ke,uid,mail,pass,details) VALUES (?,?,?,?,?)', - [ - form.ke, - form.uid, - form.mail, - s.createHash(form.pass), - form.details - ] - ) + s.knexQuery({ + action: "insert", + table: "Users", + insert: { + ke: form.ke, + uid: form.uid, + mail: form.mail, + pass: s.createHash(form.pass), + details: form.details + } + }) s.tx({f:'add_account',details:form.details,ke:form.ke,uid:form.uid,mail:form.mail},'$') endData.user = Object.assign(form,{}) //init user @@ -315,12 +297,19 @@ module.exports = function(s,config,lang,app){ ok : false } var close = function(){ - res.end(s.prettyPrint(endData)) + s.closeJsonResponse(res,endData) } var form = s.getPostData(req) if(form){ var account = s.getPostData(req,'account') - s.sqlQuery('SELECT * FROM Users WHERE mail=?',[account.mail],function(err,r) { + s.knexQuery({ + action: "select", + columns: "*", + table: "Users", + where: [ + ['mail','=',account.mail] + ] + },(err,r) => { if(r && r[0]){ r = r[0] var details = JSON.parse(r.details) @@ -337,25 +326,16 @@ module.exports = function(s,config,lang,app){ } delete(form.password_again); delete(form.pass_again); - var keys = Object.keys(form) - var set = [] - var values = [] - keys.forEach(function(v,n){ - if( - set === 'ke' || - !form[v] - ){ - //skip - return - } - set.push(v+'=?') - if(v === 'details'){ - form[v] = s.stringJSON(Object.assign(details,s.parseJSON(form[v]))) - } - values.push(form[v]) - }) - values.push(account.mail) - s.sqlQuery('UPDATE Users SET '+set.join(',')+' WHERE mail=?',values,function(err,r) { + delete(form.ke); + form.details = s.stringJSON(Object.assign(details,s.parseJSON(form.details))) + s.knexQuery({ + action: "update", + table: "Users", + update: form, + where: [ + ['mail','=',account.mail], + ] + },(err,r) => { if(err){ console.log(err) endData.error = err @@ -388,32 +368,79 @@ module.exports = function(s,config,lang,app){ ok : true } var close = function(){ - res.end(s.prettyPrint(endData)) + s.closeJsonResponse(res,endData) } var account = s.getPostData(req,'account') - s.sqlQuery('DELETE FROM Users WHERE uid=? AND ke=? AND mail=?',[account.uid,account.ke,account.mail]) - s.sqlQuery('DELETE FROM API WHERE uid=? AND ke=?',[account.uid,account.ke]) + s.knexQuery({ + action: "delete", + table: "Users", + where: [ + ['ke','=',account.ke], + ['uid','=',account.uid], + ['mail','=',account.mail], + ] + }) + s.knexQuery({ + action: "delete", + table: "API", + where: [ + ['ke','=',account.ke], + ['uid','=',account.uid], + ] + }) if(s.getPostData(req,'deleteSubAccounts',false) === '1'){ - s.sqlQuery('DELETE FROM Users WHERE ke=?',[account.ke]) + s.knexQuery({ + action: "delete", + table: "Users", + where: [ + ['ke','=',account.ke], + ] + }) } if(s.getPostData(req,'deleteMonitors',false) == '1'){ - s.sqlQuery('SELECT * FROM Monitors WHERE ke=?',[account.ke],function(err,monitors){ + s.knexQuery({ + action: "select", + columns: "*", + table: "Monitors", + where: [ + ['ke','=',account.ke], + ['mid','=',form.mid], + ] + },(err,monitors) => { if(monitors && monitors[0]){ monitors.forEach(function(monitor){ s.camera('stop',monitor) }) - s.sqlQuery('DELETE FROM Monitors WHERE ke=?',[account.ke]) + s.knexQuery({ + action: "delete", + table: "Monitors", + where: [ + ['ke','=',account.ke], + ] + }) } }) } if(s.getPostData(req,'deleteVideos',false) == '1'){ - s.sqlQuery('DELETE FROM Videos WHERE ke=?',[account.ke]) + s.knexQuery({ + action: "delete", + table: "Videos", + where: [ + ['ke','=',account.ke], + ] + }) fs.chmod(s.dir.videos+account.ke,0o777,function(err){ fs.unlink(s.dir.videos+account.ke,function(err){}) }) } if(s.getPostData(req,'deleteEvents',false) == '1'){ - s.sqlQuery('DELETE FROM Events WHERE ke=?',[account.ke]) + s.knexQuery({ + action: "delete", + table: "Events", + where: [ + ['ke','=',account.ke], + ] + }) } s.tx({f:'delete_account',ke:account.ke,uid:account.uid,mail:account.mail},'$') close() @@ -449,7 +476,11 @@ module.exports = function(s,config,lang,app){ if(tableName){ var tableIsSelected = s.getPostData(req,tableName) == 1 if(tableIsSelected){ - s.sqlQuery('SELECT * FROM `' + tableName +'`',[],function(err,dataRows){ + s.knexQuery({ + action: "select", + columns: "*", + table: tableName + },(err,dataRows) => { endData.database[tableName] = dataRows ++completedTables tableExportLoop(callback) @@ -551,26 +582,26 @@ module.exports = function(s,config,lang,app){ ]) break; } - var keysToCheck = [] - var valuesToCheck = [] + const whereQuery = [] fieldsToCheck.forEach(function(key){ - keysToCheck.push(key + '= ?') - valuesToCheck.push(row[key]) + whereQuery.push([key,'=',row[key]]) }) - s.sqlQuery('SELECT * FROM ' + tableName + ' WHERE ' + keysToCheck.join(' AND '),valuesToCheck,function(err,selected){ + s.knexQuery({ + action: "select", + columns: "*", + table: tableName, + where: whereQuery + },(err,selected) => { if(selected && selected[0]){ selected = selected[0] rowsExistingAlready[tableName].push(selected) callback() }else{ - var rowKeys = Object.keys(row) - var insertEscapes = [] - var insertValues = [] - rowKeys.forEach(function(key){ - insertEscapes.push('?') - insertValues.push(row[key]) - }) - s.sqlQuery('INSERT INTO ' + tableName + ' (' + rowKeys.join(',') +') VALUES (' + insertEscapes.join(',') + ')',insertValues,function(){ + s.knexQuery({ + action: "insert", + table: tableName, + insert: row + },(err) => { if(!err){ ++countOfRowsInserted[tableName] } @@ -631,7 +662,7 @@ module.exports = function(s,config,lang,app){ ok : true } s.checkForStalePurgeLocks() - res.end(s.prettyPrint(endData)) + s.closeJsonResponse(res,endData) },res,req) }) /** @@ -669,7 +700,7 @@ module.exports = function(s,config,lang,app){ ok : true, childNodes: childNodesJson, } - res.end(s.prettyPrint(endData)) + s.closeJsonResponse(res,endData) },res,req) }) } From 5a8f3d5afd4e45c643b3eabb8f2a457c0dd54d21 Mon Sep 17 00:00:00 2001 From: Moe Date: Sat, 11 Jul 2020 14:10:36 -0700 Subject: [PATCH 023/175] add generic SELECT function --- libs/sql.js | 74 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 74 insertions(+) diff --git a/libs/sql.js b/libs/sql.js index 6b85b05f..33740b7b 100644 --- a/libs/sql.js +++ b/libs/sql.js @@ -140,7 +140,81 @@ module.exports = function(s,config){ } return dbQuery } + const getDatabaseRows = function(options,callback){ + //current cant handle `end` time + var whereQuery = [ + ['ke','=',options.groupKey], + ] + const monitorRestrictions = options.monitorRestrictions + var frameLimit = parseInt(options.limit) || 500 + const chosenDate = options.date + const startDate = options.startDate ? s.stringToSqlTime(options.startDate) : null + const endDate = options.endDate ? s.stringToSqlTime(options.endDate) : null + const startOperator = options.startOperator || '>=' + const endOperator = options.endOperator || '<=' + if(chosenDate){ + if(chosenDate.indexOf('-') === -1 && !isNaN(chosenDate)){ + chosenDate = parseInt(chosenDate) + } + var selectedDate = chosenDate + if(typeof chosenDate === 'string' && chosenDate.indexOf('.') > -1){ + selectedDate = chosenDate.split('.')[0] + } + selectedDate = new Date(selectedDate) + var utcSelectedDate = new Date(selectedDate.getTime() + selectedDate.getTimezoneOffset() * 60000) + startDate = moment(utcSelectedDate).format('YYYY-MM-DD HH:mm:ss') + var dayAfter = utcSelectedDate + dayAfter.setDate(dayAfter.getDate() + 1) + endDate = moment(dayAfter).format('YYYY-MM-DD HH:mm:ss') + } + if(startDate){ + if(endDate){ + whereQuery.push(['time',startOperator,startDate]) + whereQuery.push(['time',endOperator,endDate]) + }else{ + whereQuery.push(['time',startOperator,startDate]) + } + } + if(monitorRestrictions && monitorRestrictions.length > 0){ + whereQuery.push(monitorRestrictions) + } + if(options.archived){ + whereQuery.push(['details','LIKE',`%"archived":"1"%`]) + } + if(options.filename){ + whereQuery.push(['filename','=',options.filename]) + frameLimit = "1"; + } + s.knexQuery({ + action: "select", + columns: options.columns || "*", + table: options.table, + where: whereQuery, + orderBy: options.orderBy || ['time','desc'], + limit: frameLimit || '500' + },(err,r) => { + if(err){ + callback({ + ok: false, + total: 0, + limit: frameLimit, + [options.rowType || 'rows']: [] + }) + }else{ + r.forEach(function(file){ + file.details = s.parseJSON(file.details) + }) + callback({ + ok: true, + total: r.length, + limit: frameLimit, + [options.rowType || 'rows']: r + }) + } + }) + } s.knexQuery = knexQuery + s.getDatabaseRows = getDatabaseRows s.sqlQuery = function(query,values,onMoveOn,hideLog){ if(!values){values=[]} if(typeof values === 'function'){ From ef336d13d82356d35ac09e7855076b5d26270b8e Mon Sep 17 00:00:00 2001 From: Moe Date: Sat, 11 Jul 2020 14:11:39 -0700 Subject: [PATCH 024/175] sqlQuery Conversion : cleanup timelapse slightly --- libs/timelapse.js | 80 +++-------------------------------------------- 1 file changed, 5 insertions(+), 75 deletions(-) diff --git a/libs/timelapse.js b/libs/timelapse.js index 259c7268..35744be0 100644 --- a/libs/timelapse.js +++ b/libs/timelapse.js @@ -2,78 +2,6 @@ var fs = require('fs') var moment = require('moment') var express = require('express') module.exports = function(s,config,lang,app,io){ - var getFrameRows = function(options,callback){ - var whereQuery = [ - ['ke','=',options.groupKey], - ] - const monitorRestrictions = options.monitorRestrictions - var frameLimit = parseInt(options.limit) || 500 - const chosenDate = options.date - const startDate = options.startDate ? s.stringToSqlTime(options.startDate) : null - const endDate = options.endDate ? s.stringToSqlTime(options.endDate) : null - const startOperator = options.startOperator || '>=' - const endOperator = options.endOperator || '<=' - if(chosenDate){ - if(chosenDate.indexOf('-') === -1 && !isNaN(chosenDate)){ - chosenDate = parseInt(chosenDate) - } - var selectedDate = chosenDate - if(typeof chosenDate === 'string' && chosenDate.indexOf('.') > -1){ - selectedDate = chosenDate.split('.')[0] - } - selectedDate = new Date(selectedDate) - var utcSelectedDate = new Date(selectedDate.getTime() + selectedDate.getTimezoneOffset() * 60000) - startDate = moment(utcSelectedDate).format('YYYY-MM-DD HH:mm:ss') - var dayAfter = utcSelectedDate - dayAfter.setDate(dayAfter.getDate() + 1) - endDate = moment(dayAfter).format('YYYY-MM-DD HH:mm:ss') - } - if(startDate){ - if(endDate){ - whereQuery.push(['time',startOperator,startDate]) - whereQuery.push(['time',endOperator,endDate]) - }else{ - whereQuery.push(['time',startOperator,startDate]) - } - } - if(monitorRestrictions && monitorRestrictions.length > 0){ - whereQuery.push(monitorRestrictions) - } - if(options.archived){ - whereQuery.push(['details','LIKE',`%"archived":"1"%`]) - } - if(options.filename){ - whereQuery.push(['filename','=',options.filename]) - frameLimit = "1"; - } - s.knexQuery({ - action: "select", - columns: "*", - table: "Timelapse Frames", - where: whereQuery, - orderBy: ['time','desc'], - limit: frameLimit || '500' - },(err,r) => { - if(err){ - callback({ - ok: false, - total: 0, - limit: frameLimit, - frames: [] - }) - }else{ - r.forEach(function(file){ - file.details = s.parseJSON(file.details) - }) - callback({ - ok: true, - total: r.length, - limit: frameLimit, - frames: r - }) - } - }) - } s.getTimelapseFrameDirectory = function(e){ if(e.mid&&!e.id){e.id=e.mid} s.checkDetails(e) @@ -230,16 +158,18 @@ module.exports = function(s,config,lang,app,io){ return } const monitorRestrictions = s.getMonitorRestrictions(user.details,req.params.id) - getFrameRows({ + s.getDatabaseRows({ monitorRestrictions: monitorRestrictions, + table: 'Timelapse Frames', groupKey: req.params.ke, date: req.query.date, - startDate: req.query.startDate, - endDate: req.query.endDate, + startDate: req.query.start, + endDate: req.query.end, startOperator: req.query.startOperator, endOperator: req.query.endOperator, limit: req.query.limit, archived: req.query.archived, + type: 'frames' },(response) => { var isMp4Call = !!(req.query.mp4 || (req.params.date && typeof req.params.date === 'string' && req.params.date.indexOf('.') > -1)) if(isMp4Call && response.frames[0]){ From a07ae2add389680c33b8f0432d28fda888b1bf2e Mon Sep 17 00:00:00 2001 From: Moe Date: Sat, 11 Jul 2020 14:33:45 -0700 Subject: [PATCH 025/175] existing preQueries now only for MySQL databases --- libs/sql.js | 172 ++++++++++++++++++++++++++-------------------------- 1 file changed, 86 insertions(+), 86 deletions(-) diff --git a/libs/sql.js b/libs/sql.js index 33740b7b..ceb493df 100644 --- a/libs/sql.js +++ b/libs/sql.js @@ -263,94 +263,94 @@ module.exports = function(s,config){ var mySQLtail = '' if(config.databaseType === 'mysql'){ mySQLtail = ' ENGINE=InnoDB DEFAULT CHARSET=utf8' - } - //add Presets table and modernize - var createPresetsTableQuery = 'CREATE TABLE IF NOT EXISTS `Presets` ( `ke` varchar(50) DEFAULT NULL, `name` text, `details` text, `type` varchar(50) DEFAULT NULL)' - s.sqlQuery( createPresetsTableQuery + mySQLtail + ';',[],function(err){ - if(err)console.error(err) - if(config.databaseType === 'sqlite3'){ - var aQuery = "ALTER TABLE Presets RENAME TO _Presets_old;" - aQuery += createPresetsTableQuery - aQuery += "INSERT INTO Presets (`ke`, `name`, `details`, `type`) SELECT `ke`, `name`, `details`, `type` FROM _Presets_old;COMMIT;DROP TABLE _Presets_old;" - }else{ - s.sqlQuery('ALTER TABLE `Presets` CHANGE COLUMN `type` `type` VARCHAR(50) NULL DEFAULT NULL AFTER `details`;',[],function(err){ - if(err)console.error(err) - },true) - } - },true) - //add Schedules table, will remove in future - s.sqlQuery("CREATE TABLE IF NOT EXISTS `Schedules` (`ke` varchar(50) DEFAULT NULL,`name` text,`details` text,`start` varchar(10) DEFAULT NULL,`end` varchar(10) DEFAULT NULL,`enabled` int(1) NOT NULL DEFAULT '1')" + mySQLtail + ';',[],function(err){ - if(err)console.error(err) - },true) - //add Timelapses and Timelapse Frames tables, will remove in future - s.sqlQuery("CREATE TABLE IF NOT EXISTS `Timelapses` (`ke` varchar(50) NOT NULL,`mid` varchar(50) NOT NULL,`details` longtext,`date` date NOT NULL,`time` timestamp NOT NULL,`end` timestamp NOT NULL,`size` int(11)NOT NULL)" + mySQLtail + ';',[],function(err){ - if(err)console.error(err) - },true) - s.sqlQuery("CREATE TABLE IF NOT EXISTS `Timelapse Frames` (`ke` varchar(50) NOT NULL,`mid` varchar(50) NOT NULL,`details` longtext,`filename` varchar(50) NOT NULL,`time` timestamp NULL DEFAULT NULL,`size` int(11) NOT NULL)" + mySQLtail + ';',[],function(err){ - if(err)console.error(err) - },true) - //Add index to Videos table - s.sqlQuery('CREATE INDEX `videos_index` ON Videos(`time`);',[],function(err){ - if(err && err.code !== 'ER_DUP_KEYNAME'){ - console.error(err) - } - },true) - //Add index to Events table - s.sqlQuery('CREATE INDEX `events_index` ON Events(`ke`, `mid`, `time`);',[],function(err){ - if(err && err.code !== 'ER_DUP_KEYNAME'){ - console.error(err) - } - },true) - //Add index to Logs table - s.sqlQuery('CREATE INDEX `logs_index` ON Logs(`ke`, `mid`, `time`);',[],function(err){ - if(err && err.code !== 'ER_DUP_KEYNAME'){ - console.error(err) - } - },true) - //Add index to Monitors table - s.sqlQuery('CREATE INDEX `monitors_index` ON Monitors(`ke`, `mode`, `type`, `ext`);',[],function(err){ - if(err && err.code !== 'ER_DUP_KEYNAME'){ - console.error(err) - } - },true) - //Add index to Timelapse Frames table - s.sqlQuery('CREATE INDEX `timelapseframes_index` ON `Timelapse Frames`(`ke`, `mid`, `time`);',[],function(err){ - if(err && err.code !== 'ER_DUP_KEYNAME'){ - console.error(err) - } - },true) - //add Cloud Videos table, will remove in future - s.sqlQuery('CREATE TABLE IF NOT EXISTS `Cloud Videos` (`mid` varchar(50) NOT NULL,`ke` varchar(50) DEFAULT NULL,`href` text NOT NULL,`size` float DEFAULT NULL,`time` timestamp NULL DEFAULT NULL,`end` timestamp NULL DEFAULT NULL,`status` int(1) DEFAULT \'0\',`details` text)' + mySQLtail + ';',[],function(err){ - if(err)console.error(err) - },true) - //add Events Counts table, will remove in future - s.sqlQuery('CREATE TABLE IF NOT EXISTS `Events Counts` (`ke` varchar(50) NOT NULL,`mid` varchar(50) NOT NULL,`details` longtext NOT NULL,`time` timestamp NOT NULL DEFAULT current_timestamp(),`end` timestamp NOT NULL DEFAULT current_timestamp(),`count` int(10) NOT NULL DEFAULT 1,`tag` varchar(30) DEFAULT NULL)' + mySQLtail + ';',[],function(err){ - if(err && err.code !== 'ER_TABLE_EXISTS_ERROR'){ - console.error(err) - } - s.sqlQuery('ALTER TABLE `Events Counts` ADD COLUMN `time` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP AFTER `details`;',[],function(err){ - // console.error(err) + //add Presets table and modernize + var createPresetsTableQuery = 'CREATE TABLE IF NOT EXISTS `Presets` ( `ke` varchar(50) DEFAULT NULL, `name` text, `details` text, `type` varchar(50) DEFAULT NULL)' + s.sqlQuery( createPresetsTableQuery + mySQLtail + ';',[],function(err){ + if(err)console.error(err) + if(config.databaseType === 'sqlite3'){ + var aQuery = "ALTER TABLE Presets RENAME TO _Presets_old;" + aQuery += createPresetsTableQuery + aQuery += "INSERT INTO Presets (`ke`, `name`, `details`, `type`) SELECT `ke`, `name`, `details`, `type` FROM _Presets_old;COMMIT;DROP TABLE _Presets_old;" + }else{ + s.sqlQuery('ALTER TABLE `Presets` CHANGE COLUMN `type` `type` VARCHAR(50) NULL DEFAULT NULL AFTER `details`;',[],function(err){ + if(err)console.error(err) + },true) + } },true) - },true) - //add Cloud Timelapse Frames table, will remove in future - s.sqlQuery('CREATE TABLE IF NOT EXISTS `Cloud Timelapse Frames` (`ke` varchar(50) NOT NULL,`mid` varchar(50) NOT NULL,`href` text NOT NULL,`details` longtext,`filename` varchar(50) NOT NULL,`time` timestamp NULL DEFAULT NULL,`size` int(11) NOT NULL)' + mySQLtail + ';',[],function(err){ - if(err)console.error(err) - },true) - //create Files table - var createFilesTableQuery = "CREATE TABLE IF NOT EXISTS `Files` (`ke` varchar(50) NOT NULL,`mid` varchar(50) NOT NULL,`name` tinytext NOT NULL,`size` float NOT NULL DEFAULT '0',`details` text NOT NULL,`status` int(1) NOT NULL DEFAULT '0',`time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP)" - s.sqlQuery(createFilesTableQuery + mySQLtail + ';',[],function(err){ - if(err)console.error(err) - //add time column to Files table - if(config.databaseType === 'sqlite3'){ - var aQuery = "ALTER TABLE Files RENAME TO _Files_old;" - aQuery += createPresetsTableQuery - aQuery += "INSERT INTO Files (`ke`, `mid`, `name`, `details`, `size`, `status`, `time`) SELECT `ke`, `mid`, `name`, `details`, `size`, `status`, `time` FROM _Files_old;COMMIT;DROP TABLE _Files_old;" - }else{ - s.sqlQuery('ALTER TABLE `Files` ADD COLUMN `time` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP AFTER `status`;',[],function(err){ - if(err && err.sqlMessage && err.sqlMessage.indexOf('Duplicate') === -1)console.error(err) + //add Schedules table, will remove in future + s.sqlQuery("CREATE TABLE IF NOT EXISTS `Schedules` (`ke` varchar(50) DEFAULT NULL,`name` text,`details` text,`start` varchar(10) DEFAULT NULL,`end` varchar(10) DEFAULT NULL,`enabled` int(1) NOT NULL DEFAULT '1')" + mySQLtail + ';',[],function(err){ + if(err)console.error(err) + },true) + //add Timelapses and Timelapse Frames tables, will remove in future + s.sqlQuery("CREATE TABLE IF NOT EXISTS `Timelapses` (`ke` varchar(50) NOT NULL,`mid` varchar(50) NOT NULL,`details` longtext,`date` date NOT NULL,`time` timestamp NOT NULL,`end` timestamp NOT NULL,`size` int(11)NOT NULL)" + mySQLtail + ';',[],function(err){ + if(err)console.error(err) + },true) + s.sqlQuery("CREATE TABLE IF NOT EXISTS `Timelapse Frames` (`ke` varchar(50) NOT NULL,`mid` varchar(50) NOT NULL,`details` longtext,`filename` varchar(50) NOT NULL,`time` timestamp NULL DEFAULT NULL,`size` int(11) NOT NULL)" + mySQLtail + ';',[],function(err){ + if(err)console.error(err) + },true) + //Add index to Videos table + s.sqlQuery('CREATE INDEX `videos_index` ON Videos(`time`);',[],function(err){ + if(err && err.code !== 'ER_DUP_KEYNAME'){ + console.error(err) + } + },true) + //Add index to Events table + s.sqlQuery('CREATE INDEX `events_index` ON Events(`ke`, `mid`, `time`);',[],function(err){ + if(err && err.code !== 'ER_DUP_KEYNAME'){ + console.error(err) + } + },true) + //Add index to Logs table + s.sqlQuery('CREATE INDEX `logs_index` ON Logs(`ke`, `mid`, `time`);',[],function(err){ + if(err && err.code !== 'ER_DUP_KEYNAME'){ + console.error(err) + } + },true) + //Add index to Monitors table + s.sqlQuery('CREATE INDEX `monitors_index` ON Monitors(`ke`, `mode`, `type`, `ext`);',[],function(err){ + if(err && err.code !== 'ER_DUP_KEYNAME'){ + console.error(err) + } + },true) + //Add index to Timelapse Frames table + s.sqlQuery('CREATE INDEX `timelapseframes_index` ON `Timelapse Frames`(`ke`, `mid`, `time`);',[],function(err){ + if(err && err.code !== 'ER_DUP_KEYNAME'){ + console.error(err) + } + },true) + //add Cloud Videos table, will remove in future + s.sqlQuery('CREATE TABLE IF NOT EXISTS `Cloud Videos` (`mid` varchar(50) NOT NULL,`ke` varchar(50) DEFAULT NULL,`href` text NOT NULL,`size` float DEFAULT NULL,`time` timestamp NULL DEFAULT NULL,`end` timestamp NULL DEFAULT NULL,`status` int(1) DEFAULT \'0\',`details` text)' + mySQLtail + ';',[],function(err){ + if(err)console.error(err) + },true) + //add Events Counts table, will remove in future + s.sqlQuery('CREATE TABLE IF NOT EXISTS `Events Counts` (`ke` varchar(50) NOT NULL,`mid` varchar(50) NOT NULL,`details` longtext NOT NULL,`time` timestamp NOT NULL DEFAULT current_timestamp(),`end` timestamp NOT NULL DEFAULT current_timestamp(),`count` int(10) NOT NULL DEFAULT 1,`tag` varchar(30) DEFAULT NULL)' + mySQLtail + ';',[],function(err){ + if(err && err.code !== 'ER_TABLE_EXISTS_ERROR'){ + console.error(err) + } + s.sqlQuery('ALTER TABLE `Events Counts` ADD COLUMN `time` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP AFTER `details`;',[],function(err){ + // console.error(err) },true) - } - },true) + },true) + //add Cloud Timelapse Frames table, will remove in future + s.sqlQuery('CREATE TABLE IF NOT EXISTS `Cloud Timelapse Frames` (`ke` varchar(50) NOT NULL,`mid` varchar(50) NOT NULL,`href` text NOT NULL,`details` longtext,`filename` varchar(50) NOT NULL,`time` timestamp NULL DEFAULT NULL,`size` int(11) NOT NULL)' + mySQLtail + ';',[],function(err){ + if(err)console.error(err) + },true) + //create Files table + var createFilesTableQuery = "CREATE TABLE IF NOT EXISTS `Files` (`ke` varchar(50) NOT NULL,`mid` varchar(50) NOT NULL,`name` tinytext NOT NULL,`size` float NOT NULL DEFAULT '0',`details` text NOT NULL,`status` int(1) NOT NULL DEFAULT '0',`time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP)" + s.sqlQuery(createFilesTableQuery + mySQLtail + ';',[],function(err){ + if(err)console.error(err) + //add time column to Files table + if(config.databaseType === 'sqlite3'){ + var aQuery = "ALTER TABLE Files RENAME TO _Files_old;" + aQuery += createPresetsTableQuery + aQuery += "INSERT INTO Files (`ke`, `mid`, `name`, `details`, `size`, `status`, `time`) SELECT `ke`, `mid`, `name`, `details`, `size`, `status`, `time` FROM _Files_old;COMMIT;DROP TABLE _Files_old;" + }else{ + s.sqlQuery('ALTER TABLE `Files` ADD COLUMN `time` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP AFTER `status`;',[],function(err){ + if(err && err.sqlMessage && err.sqlMessage.indexOf('Duplicate') === -1)console.error(err) + },true) + } + },true) + } delete(s.preQueries) } s.sqlQueryBetweenTimesWithPermissions = (options,callback) => { From 4b7371e635522fb21de010eaaf1135ca88510205 Mon Sep 17 00:00:00 2001 From: Moe Date: Sat, 11 Jul 2020 14:44:37 -0700 Subject: [PATCH 026/175] sqlQuery Addition : plugins, childeNode --- libs/childNode.js | 11 +++++++++++ libs/plugins.js | 7 +++++-- 2 files changed, 16 insertions(+), 2 deletions(-) diff --git a/libs/childNode.js b/libs/childNode.js index 8610c19c..c8137731 100644 --- a/libs/childNode.js +++ b/libs/childNode.js @@ -66,6 +66,11 @@ module.exports = function(s,config,lang,app,io){ cn.emit('c',{f:'sqlCallback',rows:rows,err:err,callbackId:d.callbackId}); }); break; + case'knex': + s.knexQuery(d.options,function(err,rows){ + cn.emit('c',{f:'sqlCallback',rows:rows,err:err,callbackId:d.callbackId}); + }); + break; case'clearCameraFromActiveList': if(s.childNodes[ipAddress])delete(s.childNodes[ipAddress].activeCameras[d.ke + d.id]) break; @@ -213,6 +218,12 @@ module.exports = function(s,config,lang,app,io){ s.queuedSqlCallbacks[callbackId] = onMoveOn s.cx({f:'sql',query:query,values:values,callbackId:callbackId}); } + s.knexQuery = function(options,onMoveOn){ + var callbackId = s.gid() + if(typeof onMoveOn !== 'function'){onMoveOn=function(){}} + s.queuedSqlCallbacks[callbackId] = onMoveOn + s.cx({f:'knex',options:options,callbackId:callbackId}); + } setInterval(function(){ s.cpuUsage(function(cpu){ s.cx({f:'cpu',cpu:parseFloat(cpu)}) diff --git a/libs/plugins.js b/libs/plugins.js index f469e9ee..199559fb 100644 --- a/libs/plugins.js +++ b/libs/plugins.js @@ -14,11 +14,14 @@ module.exports = function(s,config,lang,io){ case's.tx': s.tx(d.data,d.to) break; + case'log': + s.systemLog('PLUGIN : '+d.plug+' : ',d) + break; case's.sqlQuery': s.sqlQuery(d.query,d.values) break; - case'log': - s.systemLog('PLUGIN : '+d.plug+' : ',d) + case's.knexQuery': + s.sqlQuery(d.options) break; } } From 64a019eac7e847026c3b07db33e808cb4ed075b3 Mon Sep 17 00:00:00 2001 From: Moe Date: Sat, 11 Jul 2020 14:45:53 -0700 Subject: [PATCH 027/175] Update plugins.js --- libs/plugins.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libs/plugins.js b/libs/plugins.js index 199559fb..70ef175d 100644 --- a/libs/plugins.js +++ b/libs/plugins.js @@ -21,7 +21,7 @@ module.exports = function(s,config,lang,io){ s.sqlQuery(d.query,d.values) break; case's.knexQuery': - s.sqlQuery(d.options) + s.knexQuery(d.options) break; } } From 0026c8bd13a6f55ce924870733f11d3211b5aaac Mon Sep 17 00:00:00 2001 From: Moe Date: Sat, 11 Jul 2020 15:54:35 -0700 Subject: [PATCH 028/175] sqlQuery Conversion : cron (All Queries Converted!) - preQueries are left as-is because they are for older installations. Older installations are expected to be on a MySQL/MariaDB type database. They may be removed in the future. --- cron.js | 204 ++++++++++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 169 insertions(+), 35 deletions(-) diff --git a/cron.js b/cron.js index 0867892f..ef24888e 100644 --- a/cron.js +++ b/cron.js @@ -136,6 +136,86 @@ s.sqlQuery = function(query,values,onMoveOn){ }) } +const processWhereCondition = (dbQuery,where,didOne) => { + var whereIsArray = where instanceof Array; + if(where[0] && where[0] instanceof Array){ + dbQuery.where(function() { + var _this = this + var didOneInsideGroup = false + where.forEach((whereInsideGroup) => { + console.log('LINE',whereInsideGroup) + processWhereCondition(_this,whereInsideGroup,didOneInsideGroup) + }) + }) + }else if(!didOne){ + didOne = true + whereIsArray ? dbQuery.where(...where) : dbQuery.where(where) + }else if(where.length === 4){ + const separator = where[0] + '' + where.shift() + switch(separator){ + case'and': + whereIsArray ? dbQuery.andWhere(...where) : dbQuery.andWhere(where) + break; + case'or': + whereIsArray ? dbQuery.orWhere(...where) : dbQuery.orWhere(where) + break; + } + }else{ + whereIsArray ? dbQuery.andWhere(...where) : dbQuery.andWhere(where) + } + +} +const knexQuery = (options,callback) => { + if(!s.databaseEngine)return// console.log('Database Not Set'); + if(config.debugLogVerbose && config.debugLog === true){ + s.debugLog('s.knexQuery QUERY',options) + } + // options = { + // action: "", + // columns: "", + // table: "" + // } + var dbQuery + switch(options.action){ + case'select': + options.columns = options.columns.indexOf(',') === -1 ? [options.columns] : options.columns.split(','); + dbQuery = s.databaseEngine.select(...options.columns).from(options.table) + break; + case'update': + dbQuery = s.databaseEngine(options.table).update(options.update) + break; + case'delete': + dbQuery = s.databaseEngine(options.table).del() + break; + case'insert': + dbQuery = s.databaseEngine(options.table).insert(options.insert) + break; + } + if(options.where){ + var didOne = false; + options.where.forEach((where) => { + processWhereCondition(dbQuery,where,didOne) + }) + } + if(options.orderBy){ + dbQuery.orderBy(...options.orderBy) + } + if(options.limit){ + dbQuery.limit(options.limit) + } + if(config.debugLog === true){ + console.log(dbQuery.toString()) + } + if(callback || options.update || options.insert){ + dbQuery.asCallback(function(err,r) { + if(err)console.log(err) + if(callback)callback(err,r) + }) + } + return dbQuery +} + s.debugLog = function(arg1,arg2){ if(config.debugLog === true){ if(!arg2)arg2 = '' @@ -236,29 +316,24 @@ const checkFilterRules = function(v,callback){ var b = v.d.filters[m]; s.debugLog(b) if(b.enabled==="1"){ - b.ar=[v.ke]; - b.sql=[]; - b.where.forEach(function(j,k){ - if(j.p1==='ke'){j.p3=v.ke} - switch(j.p3_type){ - case'function': - b.sql.push(j.p1+' '+j.p2+' '+j.p3) - break; - default: - b.sql.push(j.p1+' '+j.p2+' ?') - b.ar.push(j.p3) - break; - } + const whereQuery = [ + ['ke','=',v.ke], + ['status','!=',"0"], + ['details','NOT LIKE','%"archived":"1"%'], + ] + b.where.forEach(function(condition){ + if(condition.p1 === 'ke'){condition.p3 = v.ke} + whereQuery.push(condition.p1,condition.p2 || '=',condition.p3) }) - b.sql='WHERE ke=? AND status != 0 AND details NOT LIKE \'%"archived":"1"%\' AND ('+b.sql.join(' AND ')+')'; - if(b.sort_by&&b.sort_by!==''){ - b.sql+=' ORDER BY `'+b.sort_by+'` '+b.sort_by_direction - } - if(b.limit&&b.limit!==''){ - b.sql+=' LIMIT '+b.limit - } - s.sqlQuery('SELECT * FROM Videos '+b.sql,b.ar,function(err,r){ - if(r&&r[0]){ + s.knexQuery({ + action: "select", + columns: "*", + table: "Videos", + where: whereQuery, + orderBy: [b.sort_by,b.sort_by_direction.toLowerCase()], + limit: b.limit + },(err,r) => { + if(r && r[0]){ if(r.length > 0 || config.debugLog === true){ s.cx({f:'filterMatch',msg:r.length+' SQL rows match "'+m+'"',ke:v.ke,time:moment()}) } @@ -309,10 +384,19 @@ const deleteRowsWithNoVideo = function(v,callback){ ) ){ s.alreadyDeletedRowsWithNoVideosOnStart[v.ke]=true; - es={}; - s.sqlQuery('SELECT * FROM Videos WHERE ke=? AND status!=0 AND details NOT LIKE \'%"archived":"1"%\' AND time < ?',[v.ke,s.sqlDate('10 MINUTE')],function(err,evs){ - if(evs&&evs[0]){ - es.del=[];es.ar=[v.ke]; + s.knexQuery({ + action: "select", + columns: "*", + table: "Videos", + where: [ + ['ke','=',v.ke], + ['status','!=','0'], + ['details','NOT LIKE','%"archived":"1"%'], + ['time','<',s.sqlDate('10 MINUTE')], + ] + },(err,evs) => { + if(evs && evs[0]){ + const videosToDelete = []; evs.forEach(function(ev){ var filename var details @@ -337,8 +421,8 @@ const deleteRowsWithNoVideo = function(v,callback){ s.tx({f:'video_delete',filename:filename+'.'+ev.ext,mid:ev.mid,ke:ev.ke,time:ev.time,end:s.moment(new Date,'YYYY-MM-DD HH:mm:ss')},'GRP_'+ev.ke); } }); - if(es.del.length>0 || config.debugLog === true){ - s.cx({f:'deleteNoVideo',msg:es.del.length+' SQL rows with no file deleted',ke:v.ke,time:moment()}) + if(videosToDelete.length>0 || config.debugLog === true){ + s.cx({f:'deleteNoVideo',msg:videosToDelete.length+' SQL rows with no file deleted',ke:v.ke,time:moment()}) } } setTimeout(function(){ @@ -353,7 +437,14 @@ const deleteRowsWithNoVideo = function(v,callback){ const deleteOldLogs = function(v,callback){ if(!v.d.log_days||v.d.log_days==''){v.d.log_days=10}else{v.d.log_days=parseFloat(v.d.log_days)}; if(config.cron.deleteLogs===true&&v.d.log_days!==0){ - s.sqlQuery("DELETE FROM Logs WHERE ke=? AND `time` < ?",[v.ke,s.sqlDate(v.d.log_days+' DAY')],function(err,rrr){ + s.knexQuery({ + action: "delete", + table: "Logs", + where: [ + ['ke','=',v.ke], + ['time','<',s.sqlDate(v.d.log_days+' DAY')], + ] + },(err,rrr) => { callback() if(err)return console.error(err); if(rrr.affectedRows && rrr.affectedRows.length>0 || config.debugLog === true){ @@ -368,7 +459,14 @@ const deleteOldLogs = function(v,callback){ const deleteOldEvents = function(v,callback){ if(!v.d.event_days||v.d.event_days==''){v.d.event_days=10}else{v.d.event_days=parseFloat(v.d.event_days)}; if(config.cron.deleteEvents===true&&v.d.event_days!==0){ - s.sqlQuery("DELETE FROM Events WHERE ke=? AND `time` < ?",[v.ke,s.sqlDate(v.d.event_days+' DAY')],function(err,rrr){ + s.knexQuery({ + action: "delete", + table: "Events", + where: [ + ['ke','=',v.ke], + ['time','<',s.sqlDate(v.d.event_days+' DAY')], + ] + },(err,rrr) => { callback() if(err)return console.error(err); if(rrr.affectedRows && rrr.affectedRows.length > 0 || config.debugLog === true){ @@ -383,7 +481,14 @@ const deleteOldEvents = function(v,callback){ const deleteOldEventCounts = function(v,callback){ if(!v.d.event_days||v.d.event_days==''){v.d.event_days=10}else{v.d.event_days=parseFloat(v.d.event_days)}; if(config.cron.deleteEvents===true&&v.d.event_days!==0){ - s.sqlQuery("DELETE FROM `Events Counts` WHERE ke=? AND `time` < ?",[v.ke,s.sqlDate(v.d.event_days+' DAY')],function(err,rrr){ + s.knexQuery({ + action: "delete", + table: "Events Counts", + where: [ + ['ke','=',v.ke], + ['time','<',s.sqlDate(v.d.event_days+' DAY')], + ] + },(err,rrr) => { callback() if(err && err.code !== 'ER_NO_SUCH_TABLE')return console.error(err); if(rrr.affectedRows && rrr.affectedRows.length > 0 || config.debugLog === true){ @@ -399,7 +504,15 @@ const deleteOldFileBins = function(v,callback){ if(!v.d.fileBin_days||v.d.fileBin_days==''){v.d.fileBin_days=10}else{v.d.fileBin_days=parseFloat(v.d.fileBin_days)}; if(config.cron.deleteFileBins===true&&v.d.fileBin_days!==0){ var fileBinQuery = " FROM Files WHERE ke=? AND `time` < ?"; - s.sqlQuery("SELECT *"+fileBinQuery,[v.ke,s.sqlDate(v.d.fileBin_days+' DAY')],function(err,files){ + s.knexQuery({ + action: "select", + columns: "*", + table: "Files", + where: [ + ['ke','=',v.ke], + ['time','<',s.sqlDate(v.d.fileBin_days+' DAY')], + ] + },(err,rrr) => { if(files&&files[0]){ //delete the files files.forEach(function(file){ @@ -408,7 +521,14 @@ const deleteOldFileBins = function(v,callback){ }) }) //delete the database rows - s.sqlQuery("DELETE"+fileBinQuery,[v.ke,v.d.fileBin_days],function(err,rrr){ + s.knexQuery({ + action: "delete", + table: "Files", + where: [ + ['ke','=',v.ke], + ['time','<',s.sqlDate(v.d.fileBin_days+' DAY')], + ] + },(err,rrr) => { callback() if(err)return console.error(err); if(rrr.affectedRows && rrr.affectedRows.length>0 || config.debugLog === true){ @@ -451,7 +571,14 @@ const processUser = function(number,rows){ if(!v.d.size||v.d.size==''){v.d.size=10000}else{v.d.size=parseFloat(v.d.size)}; //days to keep videos if(!v.d.days||v.d.days==''){v.d.days=5}else{v.d.days=parseFloat(v.d.days)}; - s.sqlQuery('SELECT * FROM Monitors WHERE ke=?', [v.ke], function(err,rr) { + s.knexQuery({ + action: "select", + columns: "*", + table: "Monitors", + where: [ + ['ke','=',v.ke], + ] + },(err,rr) => { if(!v.d.filters||v.d.filters==''){ v.d.filters={}; } @@ -522,7 +649,14 @@ const clearCronInterval = function(){ } const doCronJobs = function(){ s.cx({f:'start',time:moment()}) - s.sqlQuery('SELECT ke,uid,details,mail FROM Users WHERE details NOT LIKE \'%"sub"%\'', function(err,rows) { + s.knexQuery({ + action: "select", + columns: "ke,uid,details,mail", + table: "Users", + where: [ + ['details','NOT LIKE','%"sub"%'], + ] + },(err,rows) => { if(err){ console.error(err) } From 122127f162a5fa23a3a369c3fe77839cd2bbf9db Mon Sep 17 00:00:00 2001 From: Moe Date: Sat, 11 Jul 2020 16:19:43 -0700 Subject: [PATCH 029/175] Update webServerPaths.js --- libs/webServerPaths.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libs/webServerPaths.js b/libs/webServerPaths.js index 45b8ad81..fbdff262 100644 --- a/libs/webServerPaths.js +++ b/libs/webServerPaths.js @@ -950,7 +950,7 @@ module.exports = function(s,config,lang,app,io){ app.get([config.webPaths.apiPrefix+':auth/monitor/:ke',config.webPaths.apiPrefix+':auth/monitor/:ke/:id'], function (req,res){ req.ret={ok:false}; res.setHeader('Content-Type', 'application/json'); - s.auth(req.params,(user){ + s.auth(req.params,(user) => { if(user.permissions.get_monitors==="0"){ res.end(s.prettyPrint([])) return From 875bedbc6da778cb801ccababbd03481d28047b0 Mon Sep 17 00:00:00 2001 From: Moe Date: Sat, 11 Jul 2020 18:06:07 -0700 Subject: [PATCH 030/175] Fix knexQuery error : empty condition --- libs/sql.js | 106 +++++++++++++++++++++++------------------ libs/webServerPaths.js | 20 ++++---- 2 files changed, 69 insertions(+), 57 deletions(-) diff --git a/libs/sql.js b/libs/sql.js index ceb493df..e337f20f 100644 --- a/libs/sql.js +++ b/libs/sql.js @@ -63,12 +63,12 @@ module.exports = function(s,config){ }, 4); const processWhereCondition = (dbQuery,where,didOne) => { var whereIsArray = where instanceof Array; + if(!where[0])return; if(where[0] && where[0] instanceof Array){ dbQuery.where(function() { var _this = this var didOneInsideGroup = false where.forEach((whereInsideGroup) => { - console.log('LINE',whereInsideGroup) processWhereCondition(_this,whereInsideGroup,didOneInsideGroup) }) }) @@ -91,54 +91,68 @@ module.exports = function(s,config){ } } - const knexQuery = (options,callback) => { - if(!s.databaseEngine)return// console.log('Database Not Set'); + const knexError = (dbQuery,options,err) => { + console.error('knexError----------------------------------- START') if(config.debugLogVerbose && config.debugLog === true){ - s.debugLog('s.knexQuery QUERY',options) + s.debugLog('s.knexQuery QUERY',JSON.stringify(options,null,3)) + s.debugLog('STACK TRACE, NOT AN ',new Error()) } - // options = { - // action: "", - // columns: "", - // table: "" - // } - var dbQuery - switch(options.action){ - case'select': - options.columns = options.columns.indexOf(',') === -1 ? [options.columns] : options.columns.split(','); - dbQuery = s.databaseEngine.select(...options.columns).from(options.table) - break; - case'update': - dbQuery = s.databaseEngine(options.table).update(options.update) - break; - case'delete': - dbQuery = s.databaseEngine(options.table).del() - break; - case'insert': - dbQuery = s.databaseEngine(options.table).insert(options.insert) - break; + console.error(err) + console.error(dbQuery.toString()) + console.error('knexError----------------------------------- END') + } + const knexQuery = (options,callback) => { + try{ + if(!s.databaseEngine)return// console.log('Database Not Set'); + // options = { + // action: "", + // columns: "", + // table: "" + // } + var dbQuery + switch(options.action){ + case'select': + options.columns = options.columns.indexOf(',') === -1 ? [options.columns] : options.columns.split(','); + dbQuery = s.databaseEngine.select(...options.columns).from(options.table) + break; + case'update': + dbQuery = s.databaseEngine(options.table).update(options.update) + break; + case'delete': + dbQuery = s.databaseEngine(options.table).del() + break; + case'insert': + dbQuery = s.databaseEngine(options.table).insert(options.insert) + break; + } + if(options.where){ + var didOne = false; + options.where.forEach((where) => { + processWhereCondition(dbQuery,where,didOne) + }) + } + if(options.orderBy){ + dbQuery.orderBy(...options.orderBy) + } + if(options.limit){ + dbQuery.limit(options.limit) + } + if(config.debugLog === true){ + console.log(dbQuery.toString()) + } + if(callback || options.update || options.insert){ + dbQuery.asCallback(function(err,r) { + if(err){ + knexError(dbQuery,options,err) + } + if(callback)callback(err,r) + }) + } + return dbQuery + }catch(err){ + if(callback)callback(err,[]) + knexError(dbQuery,options,err) } - if(options.where){ - var didOne = false; - options.where.forEach((where) => { - processWhereCondition(dbQuery,where,didOne) - }) - } - if(options.orderBy){ - dbQuery.orderBy(...options.orderBy) - } - if(options.limit){ - dbQuery.limit(options.limit) - } - if(config.debugLog === true){ - console.log(dbQuery.toString()) - } - if(callback || options.update || options.insert){ - dbQuery.asCallback(function(err,r) { - if(err)console.log(err) - if(callback)callback(err,r) - }) - } - return dbQuery } const getDatabaseRows = function(options,callback){ //current cant handle `end` time diff --git a/libs/webServerPaths.js b/libs/webServerPaths.js index fbdff262..fc7c830c 100644 --- a/libs/webServerPaths.js +++ b/libs/webServerPaths.js @@ -848,7 +848,7 @@ module.exports = function(s,config,lang,app,io){ res.end(s.prettyPrint([])) return } - const groupKey = user.ke + const groupKey = req.params.ke const monitorId = req.params.id const monitorRestrictions = s.getMonitorRestrictions(user.details,monitorId) s.knexQuery({ @@ -955,7 +955,7 @@ module.exports = function(s,config,lang,app,io){ res.end(s.prettyPrint([])) return } - const groupKey = user.ke + const groupKey = req.params.ke const monitorId = req.params.id const monitorRestrictions = s.getMonitorRestrictions(user.details,monitorId) s.knexQuery({ @@ -964,9 +964,7 @@ module.exports = function(s,config,lang,app,io){ table: "Monitors", where: [ ['ke','=',groupKey], - [ - monitorRestrictions - ] + monitorRestrictions ] },(err,r) => { r.forEach(function(v,n){ @@ -1222,7 +1220,7 @@ module.exports = function(s,config,lang,app,io){ res.end(s.prettyPrint([])) return } - const groupKey = user.ke + const groupKey = req.params.ke const monitorId = req.params.id const monitorRestrictions = s.getMonitorRestrictions(user.details,monitorId) s.knexQuery({ @@ -1380,7 +1378,7 @@ module.exports = function(s,config,lang,app,io){ app.get([config.webPaths.apiPrefix+':auth/fileBin/:ke',config.webPaths.apiPrefix+':auth/fileBin/:ke/:id'],function (req,res){ res.setHeader('Content-Type', 'application/json'); s.auth(req.params,(user) => { - const groupKey = user.ke + const groupKey = req.params.ke const monitorId = req.params.id const monitorRestrictions = s.getMonitorRestrictions(user.details,monitorId) s.knexQuery({ @@ -1411,7 +1409,7 @@ module.exports = function(s,config,lang,app,io){ res.end(user.lang['File Not Found']) } if (!s.group[req.params.ke].fileBin[req.params.id+'/'+req.params.file]){ - const groupKey = user.ke + const groupKey = req.params.ke const monitorId = req.params.id const monitorRestrictions = s.getMonitorRestrictions(user.details,monitorId) s.knexQuery({ @@ -1462,7 +1460,7 @@ module.exports = function(s,config,lang,app,io){ time = s.utcToLocal(time) } time = new Date(time) - const groupKey = user.ke + const groupKey = req.params.ke const monitorId = req.params.id s.knexQuery({ action: "select", @@ -1507,7 +1505,7 @@ module.exports = function(s,config,lang,app,io){ time = s.utcToLocal(time) } time = new Date(time) - const groupKey = user.ke + const groupKey = req.params.ke const monitorId = req.params.id s.knexQuery({ action: "select", @@ -1808,7 +1806,7 @@ module.exports = function(s,config,lang,app,io){ videoSet = 'Cloud Videos' break; } - const groupKey = user.ke + const groupKey = req.params.ke const monitorId = req.params.id s.knexQuery({ action: "select", From c2cab29515b6b82f6b0a683ffbaf0b9d6db19fd6 Mon Sep 17 00:00:00 2001 From: Moe Date: Sun, 12 Jul 2020 14:34:04 -0700 Subject: [PATCH 031/175] knexQuery logic fixes --- libs/monitor.js | 11 +++++++---- libs/sql.js | 16 ++++++++++++---- 2 files changed, 19 insertions(+), 8 deletions(-) diff --git a/libs/monitor.js b/libs/monitor.js index 74f3dfa1..02c42717 100644 --- a/libs/monitor.js +++ b/libs/monitor.js @@ -1743,7 +1743,8 @@ module.exports = function(s,config,lang){ permissions.allmonitors !== '1' ){ try{ - permissions.monitors = JSON.parse(permissions.monitors) + console.log(permissions) + permissions.monitors = s.parseJSON(permissions.monitors) permissions.monitors.forEach(function(v,n){ if(n === 0){ monitorRestrictions.push(['mid','=',v]) @@ -1755,9 +1756,11 @@ module.exports = function(s,config,lang){ console.log(er) } }else if( - !permissions.sub || - permissions.allmonitors !== '0' || - permissions.monitors.indexOf(monitorId) >- 1 + monitorId && ( + !permissions.sub || + permissions.allmonitors !== '0' || + permissions.monitors.indexOf(monitorId) >- 1 + ) ){ monitorRestrictions.push(['mid','=',monitorId]) } diff --git a/libs/sql.js b/libs/sql.js index e337f20f..a929c1d8 100644 --- a/libs/sql.js +++ b/libs/sql.js @@ -72,9 +72,6 @@ module.exports = function(s,config){ processWhereCondition(_this,whereInsideGroup,didOneInsideGroup) }) }) - }else if(!didOne){ - didOne = true - whereIsArray ? dbQuery.where(...where) : dbQuery.where(where) }else if(where.length === 4){ const separator = where[0] + '' where.shift() @@ -86,6 +83,9 @@ module.exports = function(s,config){ whereIsArray ? dbQuery.orWhere(...where) : dbQuery.orWhere(where) break; } + }else if(!didOne){ + didOne = true + whereIsArray ? dbQuery.where(...where) : dbQuery.where(where) }else{ whereIsArray ? dbQuery.andWhere(...where) : dbQuery.andWhere(where) } @@ -443,7 +443,15 @@ module.exports = function(s,config){ queryStringCount += ' and mid=?' queryCountValues.push(monitorId) }else{ - res.end('[]'); + if(options.noFormat){ + callback([]) + }else{ + callback({ + ok: true, + [rowName]: [], + endIsStartTo: endIsStartTo + }) + } return; } } From 93ee667f07888838b55efcbfa81fcf579dd8b552 Mon Sep 17 00:00:00 2001 From: Moe Date: Sun, 12 Jul 2020 14:34:41 -0700 Subject: [PATCH 032/175] webServerPaths : fix some permissions and responses --- libs/webServerPaths.js | 98 +++++++++++++++++++++++++++--------------- 1 file changed, 63 insertions(+), 35 deletions(-) diff --git a/libs/webServerPaths.js b/libs/webServerPaths.js index fc7c830c..21006fb1 100644 --- a/libs/webServerPaths.js +++ b/libs/webServerPaths.js @@ -844,13 +844,13 @@ module.exports = function(s,config,lang,app,io){ } const isM3u8 = req.query.type === 'm3u8' || req.query.type === 'm3u_plus' s.auth(req.params,function(user){ - if(user.permissions.get_monitors==="0"){ - res.end(s.prettyPrint([])) - return - } const groupKey = req.params.ke const monitorId = req.params.id const monitorRestrictions = s.getMonitorRestrictions(user.details,monitorId) + if(user.permissions.get_monitors === "0" || monitorRestrictions.length === 0){ + s.closeJsonResponse(res,[]); + return + } s.knexQuery({ action: "select", columns: "*", @@ -858,9 +858,7 @@ module.exports = function(s,config,lang,app,io){ where: [ ['ke','=',groupKey], ['mode','!=','stop'], - [ - monitorRestrictions - ] + monitorRestrictions ] },(err,r) => { var tvChannelMonitors = []; @@ -951,13 +949,13 @@ module.exports = function(s,config,lang,app,io){ req.ret={ok:false}; res.setHeader('Content-Type', 'application/json'); s.auth(req.params,(user) => { - if(user.permissions.get_monitors==="0"){ - res.end(s.prettyPrint([])) - return - } const groupKey = req.params.ke const monitorId = req.params.id const monitorRestrictions = s.getMonitorRestrictions(user.details,monitorId) + if(user.permissions.get_monitors === "0" || monitorRestrictions.length === 0){ + s.closeJsonResponse(res,[]); + return + } s.knexQuery({ action: "select", columns: "*", @@ -967,6 +965,7 @@ module.exports = function(s,config,lang,app,io){ monitorRestrictions ] },(err,r) => { + console.log(r) r.forEach(function(v,n){ if(s.group[v.ke] && s.group[v.ke].activeMonitors[v.mid]){ r[n].currentlyWatching = Object.keys(s.group[v.ke].activeMonitors[v.mid].watch).length @@ -1017,8 +1016,8 @@ module.exports = function(s,config,lang,app,io){ }) } }) - if(r.length===1){r=r[0];} - res.end(s.prettyPrint(r)); + if(r.length === 1)r = r[0] + s.closeJsonResponse(res,r); }) },res,req); }); @@ -1124,11 +1123,13 @@ module.exports = function(s,config,lang,app,io){ ) },(response) => { console.log(response) - s.buildVideoLinks(response.videos,{ - auth : req.params.auth, - videoParam : videoParam, - hideRemote : config.hideCloudSaveUrls, - }) + if(response && response.videos){ + s.buildVideoLinks(response.videos,{ + auth : req.params.auth, + videoParam : videoParam, + hideRemote : config.hideCloudSaveUrls, + }) + } res.end(s.prettyPrint(response)) }) },res,req); @@ -1216,22 +1217,20 @@ module.exports = function(s,config,lang,app,io){ req.ret={ok:false}; res.setHeader('Content-Type', 'application/json'); s.auth(req.params,(user) => { - if(user.permissions.get_monitors==="0"){ - res.end(s.prettyPrint([])) - return - } const groupKey = req.params.ke const monitorId = req.params.id const monitorRestrictions = s.getMonitorRestrictions(user.details,monitorId) + if(user.permissions.get_monitors === "0" || monitorRestrictions.length === 0){ + s.closeJsonResponse(res,[]); + return + } s.knexQuery({ action: "select", columns: "*", table: "Monitors", where: [ ['ke','=',groupKey], - [ - monitorRestrictions - ] + monitorRestrictions ] },(err,r) => { const startedMonitors = [] @@ -1381,15 +1380,17 @@ module.exports = function(s,config,lang,app,io){ const groupKey = req.params.ke const monitorId = req.params.id const monitorRestrictions = s.getMonitorRestrictions(user.details,monitorId) + if(user.permissions.get_monitors === "0" || monitorRestrictions.length === 0){ + s.closeJsonResponse(res,[]); + return + } s.knexQuery({ action: "select", columns: "*", table: "Files", where: [ ['ke','=',groupKey], - [ - monitorRestrictions - ] + monitorRestrictions ] },(err,r) => { r.forEach(function(v){ @@ -1412,6 +1413,13 @@ module.exports = function(s,config,lang,app,io){ const groupKey = req.params.ke const monitorId = req.params.id const monitorRestrictions = s.getMonitorRestrictions(user.details,monitorId) + if(user.permissions.get_monitors === "0" || monitorRestrictions.length === 0){ + s.closeJsonResponse(res,{ + ok: false, + msg: lang['Not Permitted'] + }) + return + } s.knexQuery({ action: "select", columns: "*", @@ -1420,9 +1428,7 @@ module.exports = function(s,config,lang,app,io){ ['ke','=',groupKey], ['mid','=',req.params.id], ['name','=',req.params.file], - [ - monitorRestrictions - ] + monitorRestrictions ] },(err,r) => { if(r && r[0]){ @@ -1451,8 +1457,14 @@ module.exports = function(s,config,lang,app,io){ */ app.get(config.webPaths.apiPrefix+':auth/cloudVideos/:ke/:id/:file', function (req,res){ s.auth(req.params,function(user){ - if(user.permissions.watch_videos==="0"||user.details.sub&&user.details.allmonitors!=='1'&&user.details.monitors.indexOf(req.params.id)===-1){ - res.end(user.lang['Not Permitted']) + const groupKey = req.params.ke + const monitorId = req.params.id + const monitorRestrictions = s.getMonitorRestrictions(user.details,monitorId) + if(user.permissions.watch_videos === "0" || monitorRestrictions.length === 0){ + s.closeJsonResponse(res,{ + ok: false, + msg: lang['Not Permitted'] + }) return } var time = s.nameToTime(req.params.file) @@ -1496,8 +1508,14 @@ module.exports = function(s,config,lang,app,io){ */ app.get(config.webPaths.apiPrefix+':auth/videos/:ke/:id/:file', function (req,res){ s.auth(req.params,function(user){ - if(user.permissions.watch_videos==="0"||user.details.sub&&user.details.allmonitors!=='1'&&user.details.monitors.indexOf(req.params.id)===-1){ - res.end(user.lang['Not Permitted']) + const groupKey = req.params.ke + const monitorId = req.params.id + const monitorRestrictions = s.getMonitorRestrictions(user.details,monitorId) + if(user.permissions.watch_videos === "0" || monitorRestrictions.length === 0){ + s.closeJsonResponse(res,{ + ok: false, + msg: lang['Not Permitted'] + }) return } var time = s.nameToTime(req.params.file) @@ -1538,6 +1556,16 @@ module.exports = function(s,config,lang,app,io){ */ app.get(config.webPaths.apiPrefix+':auth/motion/:ke/:id', function (req,res){ s.auth(req.params,function(user){ + const groupKey = req.params.ke + const monitorId = req.params.id + const monitorRestrictions = s.getMonitorRestrictions(user.details,monitorId) + if(monitorRestrictions.length === 0){ + s.closeJsonResponse(res,{ + ok: false, + msg: lang['Not Permitted'] + }) + return + } if(req.query.data){ try{ var d = { From a72ea774a8b040176e7a445118f029788bc06127 Mon Sep 17 00:00:00 2001 From: Ian Rubado Date: Mon, 13 Jul 2020 21:50:52 -0400 Subject: [PATCH 033/175] Optionally allow recording to start on motion prior to object detection results. --- definitions/en_CA.js | 19 +++++++++++++++++++ languages/en_CA.json | 3 ++- libs/events.js | 4 +++- 3 files changed, 24 insertions(+), 2 deletions(-) diff --git a/definitions/en_CA.js b/definitions/en_CA.js index ce385e99..a5d786ab 100644 --- a/definitions/en_CA.js +++ b/definitions/en_CA.js @@ -3084,6 +3084,25 @@ module.exports = function(s,config,lang){ "form-group-class": "h_casc_input h_casc_1", "possible": "" }, + { + "name": "detail=detector_always_record", + "field": lang['Start recording on motion'], + "description": "", + "default": "0", + "example": "", + "selector": "h_det_alwy_rec", + "fieldType": "select", + "possible": [ + { + "name": lang.No, + "value": "0" + }, + { + "name": lang.Yes, + "value": "1" + } + ] + }, { hidden: true, "name": "detail=detector_scale_x_object", diff --git a/languages/en_CA.json b/languages/en_CA.json index 4ec5f06a..99939555 100644 --- a/languages/en_CA.json +++ b/languages/en_CA.json @@ -1010,5 +1010,6 @@ "There are no monitors that you can view with this account.":"There are no monitors that you can view with this account.", "Delete Monitors and Files": "Delete Monitors and Files", "Select atleast one monitor to delete": "Select atleast one monitor to delete.", - "Use Built-In":"Use Built-In" + "Use Built-In":"Use Built-In", + "Start recording on motion":"Start recording on motion" } diff --git a/libs/events.js b/libs/events.js index 43c26792..999ccb3c 100644 --- a/libs/events.js +++ b/libs/events.js @@ -375,7 +375,9 @@ module.exports = function(s,config,lang){ time : s.formattedTime(), frame : s.group[d.ke].activeMonitors[d.id].lastJpegDetectorFrame }) - }else{ + } + // + if(currentConfig.detector_always_record === '1' || d.doObjectDetection !== true ){ if(currentConfig.det_multi_trig === '1'){ s.getCamerasForMultiTrigger(d.mon).forEach(function(monitor){ if(monitor.mid !== d.id){ From d6bf8e058ba27df4d88e15695fb36b482936b0a7 Mon Sep 17 00:00:00 2001 From: Moe Date: Tue, 14 Jul 2020 23:43:01 -0700 Subject: [PATCH 034/175] fix reoccurrring const groupKey --- libs/webServerPaths.js | 2 -- 1 file changed, 2 deletions(-) diff --git a/libs/webServerPaths.js b/libs/webServerPaths.js index 21006fb1..33fae6aa 100644 --- a/libs/webServerPaths.js +++ b/libs/webServerPaths.js @@ -1472,8 +1472,6 @@ module.exports = function(s,config,lang,app,io){ time = s.utcToLocal(time) } time = new Date(time) - const groupKey = req.params.ke - const monitorId = req.params.id s.knexQuery({ action: "select", columns: "*", From 155b9452857d7b0a9e1ba2700c41070c1da502ef Mon Sep 17 00:00:00 2001 From: Moe Date: Tue, 14 Jul 2020 23:49:31 -0700 Subject: [PATCH 035/175] fix reoccurrring const groupKey+ --- libs/webServerPaths.js | 2 -- 1 file changed, 2 deletions(-) diff --git a/libs/webServerPaths.js b/libs/webServerPaths.js index 33fae6aa..b88c863d 100644 --- a/libs/webServerPaths.js +++ b/libs/webServerPaths.js @@ -1521,8 +1521,6 @@ module.exports = function(s,config,lang,app,io){ time = s.utcToLocal(time) } time = new Date(time) - const groupKey = req.params.ke - const monitorId = req.params.id s.knexQuery({ action: "select", columns: "*", From cf91cf85ea248b88195e230448e4a1fdc4900961 Mon Sep 17 00:00:00 2001 From: Moe Date: Wed, 22 Jul 2020 21:19:16 -0700 Subject: [PATCH 036/175] Update Dashcam (Shinobi Streamer) data Input --- libs/cameraThread/singleCamera.js | 28 ++++++--- libs/monitor.js | 2 +- libs/webServerPaths.js | 94 ++++++++++++++----------------- 3 files changed, 63 insertions(+), 61 deletions(-) diff --git a/libs/cameraThread/singleCamera.js b/libs/cameraThread/singleCamera.js index 0536e665..b922ecf3 100644 --- a/libs/cameraThread/singleCamera.js +++ b/libs/cameraThread/singleCamera.js @@ -18,7 +18,7 @@ var stdioWriters = []; var writeToStderr = function(text){ try{ - stdioWriters[2].write(Buffer.from(`${text}`, 'utf8' )) + process.stderr.write(Buffer.from(`${text}`, 'utf8' )) // stdioWriters[2].write(Buffer.from(`${new Error('writeToStderr').stack}`, 'utf8' )) }catch(err){ // fs.appendFileSync('/home/Shinobi/test.log',text + '\n','utf8') @@ -45,10 +45,14 @@ process.on('uncaughtException', function (err) { writeToStderr(err.stack); }); const exitAction = function(){ - if(isWindows){ - spawn("taskkill", ["/pid", cameraProcess.pid, '/f', '/t']) - }else{ - process.kill(-cameraProcess.pid) + try{ + if(isWindows){ + spawn("taskkill", ["/pid", cameraProcess.pid, '/f', '/t']) + }else{ + process.kill(-cameraProcess.pid) + } + }catch(err){ + } } process.on('SIGTERM', exitAction); @@ -58,7 +62,7 @@ process.on('exit', exitAction); for(var i=0; i < stdioPipes; i++){ switch(i){ case 0: - newPipes[i] = null + newPipes[i] = 'pipe' break; case 1: newPipes[i] = 1 @@ -115,7 +119,7 @@ if(rawMonitorConfig.details.detector === '1' && rawMonitorConfig.details.detecto writeToStderr(err.stack) } } - + if(rawMonitorConfig.type === 'jpeg'){ var recordingSnapRequest var recordingSnapper @@ -197,3 +201,13 @@ if(rawMonitorConfig.type === 'jpeg'){ captureOne() },5000) } + +if( + rawMonitorConfig.type === 'dashcam' || + rawMonitorConfig.type === 'socket' +){ + process.stdin.on('data',(data) => { + //confirmed receiving data this way. + cameraProcess.stdin.write(data) + }) +} diff --git a/libs/monitor.js b/libs/monitor.js index d2c088af..1658e659 100644 --- a/libs/monitor.js +++ b/libs/monitor.js @@ -1209,7 +1209,7 @@ module.exports = function(s,config,lang){ createCameraFfmpegProcess(e) createCameraStreamHandlers(e) createEventCounter(e) - if(e.type === 'dashcam'){ + if(e.type === 'dashcam' || e.type === 'socket'){ setTimeout(function(){ activeMonitor.allowStdinWrite = true s.txToDashcamUsers({ diff --git a/libs/webServerPaths.js b/libs/webServerPaths.js index 9646791b..83774874 100644 --- a/libs/webServerPaths.js +++ b/libs/webServerPaths.js @@ -1756,54 +1756,28 @@ module.exports = function(s,config,lang,app,io){ }); } else { let video = req.files.video; - if(req.query.streamIn === '1'){ - var tempLocation = s.getStreamsDirectory(monitor) + video.name; - video.mv(tempLocation,function(){ - var fileStream = fs.createReadStream(tempLocation) - fileStream.on('close',function(){ - - }) - fileStream.on('data',function(data){ - try{ - s.group[groupKey].activeMonitors[monitorId].spawn.stdin.write(data); - }catch(err){ - console.log(err) - } - }) - // s.group[groupKey].activeMonitors[monitorId].spawn.stdin.write(fs.readFileSync(tempLocation,'binary')); + var time = new Date(parseInt(video.name.split('.')[0])) + time = req.body.startTime ? !time.getTime() ? new Date(parseInt(req.body.startTime)) : time : new Date() + var filename = s.formattedTime(time) + '.' + monitor.ext + video.mv(s.getVideoDirectory(monitor) + filename,function(){ + s.insertCompletedVideo(monitor,{ + file: filename, + events: s.group[groupKey].activeMonitors[monitorId].detector_motion_count, + endTime: req.body.endTime.indexOf('-') > -1 ? s.nameToTime(req.body.endTime) : parseInt(req.body.endTime) || null, + },function(){ + response.ok = true + response.filename = filename res.end(s.prettyPrint({ ok: true, - message: 'File is transcoding', + message: 'File is uploaded', data: { name: video.name, mimetype: video.mimetype, size: video.size } })) - }); - }else{ - var time = new Date(parseInt(video.name.split('.')[0])) - var filename = s.formattedTime(time) + '.' + monitor.ext - video.mv(s.getVideoDirectory(monitor) + filename,function(){ - s.insertCompletedVideo(monitor,{ - file: filename, - events: s.group[groupKey].activeMonitors[monitorId].detector_motion_count, - endTime: req.body.endTime.indexOf('-') > -1 ? s.nameToTime(req.body.endTime) : parseInt(req.body.endTime) || null, - },function(){ - response.ok = true - response.filename = filename - res.end(s.prettyPrint({ - ok: true, - message: 'File is uploaded', - data: { - name: video.name, - mimetype: video.mimetype, - size: video.size - } - })) - }) - }); - } + }) + }); } } catch (err) { response.err = err @@ -1900,24 +1874,38 @@ module.exports = function(s,config,lang,app,io){ /** * API : Stream In to push data to ffmpeg by HTTP */ - app.all(['/streamIn/:ke/:id','/streamIn/:ke/:id/:feed'], function (req, res) { - var checkOrigin = function(search){return req.headers.host.indexOf(search)>-1} - if(checkOrigin('127.0.0.1')){ - if(!req.params.feed){req.params.feed='1'} - if(!s.group[req.params.ke].activeMonitors[req.params.id].streamIn[req.params.feed]){ - s.group[req.params.ke].activeMonitors[req.params.id].streamIn[req.params.feed] = new events.EventEmitter().setMaxListeners(0) - } - //req.params.feed = Feed Number + app.all('/:auth/streamIn/:ke/:id', function (req, res) { + s.auth(req.params,function(user){ + const ipAddress = s.getClientIp(req) + const groupKey = req.params.ke + const monitorId = req.params.id + const timeStartedConnection = new Date(); + s.userLog({ + ke: groupKey, + mid: monitorId, + },{ + type: "HTTP streamIn Started", + msg: { + ipAddress: ipAddress, + } + }) res.connection.setTimeout(0); req.on('data', function(buffer){ - s.group[req.params.ke].activeMonitors[req.params.id].streamIn[req.params.feed].emit('data',buffer) + s.group[groupKey].activeMonitors[monitorId].spawn.stdin.write(buffer) }); req.on('end',function(){ - // console.log('streamIn closed',req.params); + s.userLog({ + ke: groupKey, + mid: monitorId, + },{ + type: "HTTP streamIn Closed", + msg: { + timeStartedConnection: timeStartedConnection, + ipAddress: ipAddress, + } + }) }); - }else{ - res.end('Local connection is only allowed.') - } + },res,req) }) /** * API : Account Edit from Dashboard From c7c8d620e1b7319201181b912d414cf6c386d604 Mon Sep 17 00:00:00 2001 From: Moe Date: Wed, 22 Jul 2020 21:19:51 -0700 Subject: [PATCH 037/175] Capture startup video counting errors and post to systemLog --- libs/startup.js | 32 ++++++++++++++++++-------------- 1 file changed, 18 insertions(+), 14 deletions(-) diff --git a/libs/startup.js b/libs/startup.js index 2ee97596..af811318 100644 --- a/libs/startup.js +++ b/libs/startup.js @@ -181,20 +181,24 @@ module.exports = function(s,config,lang,io){ }) var loadCloudVideos = function(callback){ 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' - var videoSize = video.size / 1048576 - user.cloudDiskUse[storageType].usedSpace += videoSize - user.cloudDiskUse[storageType].usedSpaceVideos += videoSize - ++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) - }) + try{ + if(videos && videos[0]){ + videos.forEach(function(video){ + var storageType = JSON.parse(video.details).type + if(!storageType)storageType = 's3' + var videoSize = video.size / 1048576 + user.cloudDiskUse[storageType].usedSpace += videoSize + user.cloudDiskUse[storageType].usedSpaceVideos += videoSize + ++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) + }) + } + }catch(err){ + s.systemLog(err) } callback() }) From 874f774d9a8670e835bc3ea835747ada1e41a4aa Mon Sep 17 00:00:00 2001 From: Moe Date: Wed, 22 Jul 2020 21:21:09 -0700 Subject: [PATCH 038/175] change to reason instead of "Motion" as title for email screenshot filename --- libs/events.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libs/events.js b/libs/events.js index 43c26792..fb84556f 100644 --- a/libs/events.js +++ b/libs/events.js @@ -438,7 +438,7 @@ module.exports = function(s,config,lang){ } d.currentTime = new Date() d.currentTimestamp = s.timeObject(d.currentTime).format() - d.screenshotName = 'Motion_'+(d.mon.name.replace(/[^\w\s]/gi,''))+'_'+d.id+'_'+d.ke+'_'+s.formattedTime() + d.screenshotName = d.details.reason + '_'+(d.mon.name.replace(/[^\w\s]/gi,''))+'_'+d.id+'_'+d.ke+'_'+s.formattedTime() d.screenshotBuffer = null s.onEventTriggerExtensions.forEach(function(extender){ From e6b5f42ce44df6547b0706f92b5bb45725d54fd3 Mon Sep 17 00:00:00 2001 From: Moe Date: Wed, 22 Jul 2020 21:21:34 -0700 Subject: [PATCH 039/175] minor housekeeping --- libs/notification.js | 2 +- plugins/pluginBase.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/libs/notification.js b/libs/notification.js index b7aa4b37..10f1f730 100644 --- a/libs/notification.js +++ b/libs/notification.js @@ -293,7 +293,7 @@ module.exports = function(s,config,lang){ detector_mail_timeout = parseFloat(d.mon.details.detector_mail_timeout)*1000*60; } //lock mailer so you don't get emailed on EVERY trigger event. - s.group[d.ke].activeMonitors[d.id].detector_mail=setTimeout(function(){ + s.group[d.ke].activeMonitors[d.id].detector_mail = setTimeout(function(){ //unlock so you can mail again. clearTimeout(s.group[d.ke].activeMonitors[d.id].detector_mail); delete(s.group[d.ke].activeMonitors[d.id].detector_mail); diff --git a/plugins/pluginBase.js b/plugins/pluginBase.js index b017fea3..1be8df9d 100644 --- a/plugins/pluginBase.js +++ b/plugins/pluginBase.js @@ -237,7 +237,7 @@ module.exports = function(__dirname, config){ } processImage(buffer,d,tx,d.frameLocation) break; - case'frame':'' + case'frame': try{ if(!s.group[d.ke]){ s.group[d.ke]={} From 8469de215ed6e14f0ad31035ee76138dcebf5837 Mon Sep 17 00:00:00 2001 From: Moe Date: Wed, 22 Jul 2020 21:22:25 -0700 Subject: [PATCH 040/175] Fix CUDA apt pointer --- INSTALL/cuda-10-2.sh | 2 +- INSTALL/cuda.sh | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/INSTALL/cuda-10-2.sh b/INSTALL/cuda-10-2.sh index 2f4f6d09..4f9e7c34 100644 --- a/INSTALL/cuda-10-2.sh +++ b/INSTALL/cuda-10-2.sh @@ -12,7 +12,7 @@ if [ -x "$(command -v apt)" ]; then sudo apt-get update -y - sudo apt-get -o Dpkg::Options::="--force-overwrite" install cuda -y --no-install-recommends + sudo apt-get -o Dpkg::Options::="--force-overwrite" install cuda-toolkit-10-2 -y --no-install-recommends sudo apt-get -o Dpkg::Options::="--force-overwrite" install --fix-broken -y # Install CUDA DNN diff --git a/INSTALL/cuda.sh b/INSTALL/cuda.sh index 2f4f6d09..4f9e7c34 100644 --- a/INSTALL/cuda.sh +++ b/INSTALL/cuda.sh @@ -12,7 +12,7 @@ if [ -x "$(command -v apt)" ]; then sudo apt-get update -y - sudo apt-get -o Dpkg::Options::="--force-overwrite" install cuda -y --no-install-recommends + sudo apt-get -o Dpkg::Options::="--force-overwrite" install cuda-toolkit-10-2 -y --no-install-recommends sudo apt-get -o Dpkg::Options::="--force-overwrite" install --fix-broken -y # Install CUDA DNN From 05f6b023080da9db64dcc587939993e039702f6a Mon Sep 17 00:00:00 2001 From: Moe Date: Wed, 22 Jul 2020 21:22:37 -0700 Subject: [PATCH 041/175] minor clean up --- web/libs/css/dash2.basic.css | 3 --- web/pages/blocks/mainpermissions.ejs | 1 - 2 files changed, 4 deletions(-) diff --git a/web/libs/css/dash2.basic.css b/web/libs/css/dash2.basic.css index 7b8d2891..1357f87d 100644 --- a/web/libs/css/dash2.basic.css +++ b/web/libs/css/dash2.basic.css @@ -182,9 +182,6 @@ img{max-width:100%} .dot-orange {background:#c49a68} .dot-grey {background:#777} - - - .os_bars{width:600px;display:inline-block;padding:5px 0 0 10px} @media screen and (max-width: 600px){ .os_bars{width:200px;} diff --git a/web/pages/blocks/mainpermissions.ejs b/web/pages/blocks/mainpermissions.ejs index 4b4042a9..7fbbd330 100644 --- a/web/pages/blocks/mainpermissions.ejs +++ b/web/pages/blocks/mainpermissions.ejs @@ -295,7 +295,6 @@ $.aC.e.on('click','.delete',function(e){ e.html='Do you want to delete '+e.account.mail+'? You cannot recover this account. Files will remain in the filesystem. If you choose to create an account with the same Group Key it will have the previous events activated in that account.' $.confirm.body.html(e.html) $.confirm.click({title:'Delete',class:'btn-danger'},function(){ - // $.ccio.cx({f:'accounts',ff:'delete',account:e.account}) $.post('<%=originalURL%><%=config.webPaths.superApiPrefix%>'+$user.sessionKey+'/accounts/deleteAdmin',{ account : e.account, // "deleteSubAccounts" : "1", From ba5743e3801ef240507cf75bdf909916fc51b104 Mon Sep 17 00:00:00 2001 From: Moe Date: Fri, 24 Jul 2020 10:31:04 -0700 Subject: [PATCH 042/175] set "Test Trigger" button to result in 100% change not 197% --- web/libs/js/dash2.elements.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/web/libs/js/dash2.elements.js b/web/libs/js/dash2.elements.js index fdcdcbc0..692339bb 100644 --- a/web/libs/js/dash2.elements.js +++ b/web/libs/js/dash2.elements.js @@ -412,7 +412,7 @@ $(document).ready(function(e){ } break; case'trigger-event': - $.getJSON(getApiPrefix() + '/motion/'+e.ke+'/'+e.mid+'/?data={"plug":"camera1","name":"stairs","reason":"motion","confidence":197.4755859375}',function(d){ + $.getJSON(getApiPrefix() + '/motion/'+e.ke+'/'+e.mid+'/?data={"plug":"camera1","name":"stairs","reason":"motion","confidence":100}',function(d){ $.ccio.log(d) }) break; From 7d07124ac54529ea77144a29c8bc7ac7b7da9bbe Mon Sep 17 00:00:00 2001 From: Moe Date: Sat, 25 Jul 2020 22:40:35 -0700 Subject: [PATCH 043/175] force image format for image in Email Notifcation (Discord as well) - This should hopefully fix users with broken images in their email notifications. -- Audio was not being stripped and was being encoded with the frame (JPEG cannot hold audio, duh) -- image2 format specified --- libs/monitor.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libs/monitor.js b/libs/monitor.js index 1658e659..1e55ae88 100644 --- a/libs/monitor.js +++ b/libs/monitor.js @@ -142,7 +142,7 @@ module.exports = function(s,config,lang){ var snapBuffer = [] var temporaryImageFile = streamDir + s.gid(5) + '.jpg' var iconImageFile = streamDir + 'icon.jpg' - var ffmpegCmd = s.splitForFFPMEG(`-loglevel warning -re -probesize 100000 -analyzeduration 100000 ${inputOptions.join(' ')} -i "${url}" ${outputOptions.join(' ')} -vf "fps=1" -vframes 1 "${temporaryImageFile}"`) + var ffmpegCmd = s.splitForFFPMEG(`-loglevel warning -re -probesize 100000 -analyzeduration 100000 ${inputOptions.join(' ')} -i "${url}" ${outputOptions.join(' ')} -f image2 -an -vf "fps=1" -vframes 1 "${temporaryImageFile}"`) fs.writeFileSync(s.group[monitor.ke].activeMonitors[monitor.id].sdir + 'snapCmd.txt',JSON.stringify({ cmd: ffmpegCmd, temporaryImageFile: temporaryImageFile, From 776a7b7f74d9c587cfd9b873f40751892ce7e053 Mon Sep 17 00:00:00 2001 From: Moe Date: Sat, 25 Jul 2020 23:15:24 -0700 Subject: [PATCH 044/175] allow adding details to externally uploaded video file --- libs/videos.js | 2 +- libs/webServerPaths.js | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/libs/videos.js b/libs/videos.js index e3bf0c5e..a6531b59 100644 --- a/libs/videos.js +++ b/libs/videos.js @@ -108,7 +108,7 @@ module.exports = function(s,config,lang){ } if(k.fileExists===true){ //close video row - k.details = {} + k.details = k.details && k.details instanceof Object ? k.details : {} k.stat = fs.statSync(k.dir+k.file) k.filesize = k.stat.size k.filesizeMB = parseFloat((k.filesize/1048576).toFixed(2)) diff --git a/libs/webServerPaths.js b/libs/webServerPaths.js index 83774874..d7b0dac8 100644 --- a/libs/webServerPaths.js +++ b/libs/webServerPaths.js @@ -1756,12 +1756,14 @@ module.exports = function(s,config,lang,app,io){ }); } else { let video = req.files.video; + var details = s.getPostData(req,'details',true) || {} var time = new Date(parseInt(video.name.split('.')[0])) time = req.body.startTime ? !time.getTime() ? new Date(parseInt(req.body.startTime)) : time : new Date() var filename = s.formattedTime(time) + '.' + monitor.ext video.mv(s.getVideoDirectory(monitor) + filename,function(){ s.insertCompletedVideo(monitor,{ file: filename, + details: details, events: s.group[groupKey].activeMonitors[monitorId].detector_motion_count, endTime: req.body.endTime.indexOf('-') > -1 ? s.nameToTime(req.body.endTime) : parseInt(req.body.endTime) || null, },function(){ From 795703cfafb3a2d44c677a2c0106d90bc9fa9ec2 Mon Sep 17 00:00:00 2001 From: Moe Date: Mon, 27 Jul 2020 18:12:57 -0700 Subject: [PATCH 045/175] sqlQuery Conversion : The Last Samurai... err... Function --- libs/sql.js | 194 ++++++++++++++---------------------- libs/timelapse.js | 3 +- libs/webServerSuperPaths.js | 1 + 3 files changed, 78 insertions(+), 120 deletions(-) diff --git a/libs/sql.js b/libs/sql.js index a929c1d8..368128bb 100644 --- a/libs/sql.js +++ b/libs/sql.js @@ -115,6 +115,11 @@ module.exports = function(s,config){ options.columns = options.columns.indexOf(',') === -1 ? [options.columns] : options.columns.split(','); dbQuery = s.databaseEngine.select(...options.columns).from(options.table) break; + case'count': + options.columns = options.columns.indexOf(',') === -1 ? [options.columns] : options.columns.split(','); + dbQuery = s.databaseEngine(options.table) + dbQuery.count(options.columns) + break; case'update': dbQuery = s.databaseEngine(options.table).update(options.update) break; @@ -135,7 +140,12 @@ module.exports = function(s,config){ dbQuery.orderBy(...options.orderBy) } if(options.limit){ - dbQuery.limit(options.limit) + if(`${options.limit}`.indexOf(',') === -1){ + dbQuery.limit(options.limit) + }else{ + const limitParts = `${options.limit}`.split(',') + dbQuery.limit(limitParts[0]).offset(limitParts[1]) + } } if(config.debugLog === true){ console.log(dbQuery.toString()) @@ -146,6 +156,11 @@ module.exports = function(s,config){ knexError(dbQuery,options,err) } if(callback)callback(err,r) + if(config.debugLogVerbose && config.debugLog === true){ + s.debugLog('s.knexQuery QUERY',JSON.stringify(options,null,3)) + s.debugLog('s.knexQuery RESPONSE',JSON.stringify(r,null,3)) + s.debugLog('STACK TRACE, NOT AN ',new Error()) + } }) } return dbQuery @@ -161,11 +176,13 @@ module.exports = function(s,config){ ] const monitorRestrictions = options.monitorRestrictions var frameLimit = parseInt(options.limit) || 500 + const endIsStartTo = options.endIsStartTo const chosenDate = options.date const startDate = options.startDate ? s.stringToSqlTime(options.startDate) : null const endDate = options.endDate ? s.stringToSqlTime(options.endDate) : null const startOperator = options.startOperator || '>=' const endOperator = options.endOperator || '<=' + const rowType = options.rowType || 'rows' if(chosenDate){ if(chosenDate.indexOf('-') === -1 && !isNaN(chosenDate)){ chosenDate = parseInt(chosenDate) @@ -184,7 +201,7 @@ module.exports = function(s,config){ if(startDate){ if(endDate){ whereQuery.push(['time',startOperator,startDate]) - whereQuery.push(['time',endOperator,endDate]) + whereQuery.push([endIsStartTo ? 'time' : 'end',endOperator,endDate]) }else{ whereQuery.push(['time',startOperator,startDate]) } @@ -200,7 +217,7 @@ module.exports = function(s,config){ frameLimit = "1"; } s.knexQuery({ - action: "select", + action: options.count ? "count" : "select", columns: options.columns || "*", table: options.table, where: whereQuery, @@ -212,7 +229,7 @@ module.exports = function(s,config){ ok: false, total: 0, limit: frameLimit, - [options.rowType || 'rows']: [] + [rowType]: [] }) }else{ r.forEach(function(file){ @@ -222,7 +239,7 @@ module.exports = function(s,config){ ok: true, total: r.length, limit: frameLimit, - [options.rowType || 'rows']: r + [rowType]: r }) } }) @@ -382,20 +399,8 @@ module.exports = function(s,config){ // parseRowDetails: true, // rowName: 'counts' // } - const user = options.user - const groupKey = options.groupKey - const monitorId = options.monitorId - const limit = options.limit - const archived = options.archived - const theTableSelected = options.table - const endIsStartTo = options.endIsStartTo - const userDetails = user.details const rowName = options.rowName || 'rows' const preliminaryValidationFailed = options.preliminaryValidationFailed || false - var endTime = options.endTime - var startTimeOperator = options.startTimeOperator - var endTimeOperator = options.endTimeOperator - var startTime = options.startTime if(preliminaryValidationFailed){ if(options.noFormat){ callback([]); @@ -407,104 +412,38 @@ module.exports = function(s,config){ } return } - var queryString = 'SELECT * FROM `' + theTableSelected + '` WHERE ke=?' - var queryValues = [groupKey] - var queryStringCount = 'SELECT COUNT(*) FROM `' + theTableSelected + '` WHERE ke=?' - var queryCountValues = [groupKey] - if(archived === '1'){ - queryString += ` AND details LIKE '%"archived":"1"'` - queryStringCount += ` AND details LIKE '%"archived":"1"'` - } - if(!monitorId){ - if( - userDetails.sub && - userDetails.monitors && - userDetails.allmonitors !== '1' - ){ - try{ - userDetails.monitors = JSON.parse(userDetails.monitors) - }catch(er){} - var queryWheres = [] - userDetails.monitors.forEach(function(v,n){ - queryWheres.push('mid=?') - queryValues.push(v) - }) - queryString += ' AND ('+queryWheres.join(' OR ')+')' - queryStringCount += ' AND ('+queryWheres.join(' OR ')+')' - } - }else{ - if( - !userDetails.sub || - userDetails.allmonitors !== '0' || - userDetails.monitors.indexOf(monitorId) >- 1 - ){ - queryString += ' and mid=?' - queryValues.push(monitorId) - queryStringCount += ' and mid=?' - queryCountValues.push(monitorId) - }else{ - if(options.noFormat){ - callback([]) - }else{ - callback({ - ok: true, - [rowName]: [], - endIsStartTo: endIsStartTo - }) - } - return; - } - } - if(startTime || endTime){ - if(startTime && startTime !== ''){ - startTime = s.stringToSqlTime(startTime) - } - if(endTime && endTime !== ''){ - endTime = s.stringToSqlTime(endTime) - } - if(!startTimeOperator || startTimeOperator==''){ - startTimeOperator = startTimeOperator || '>=' - } - if(!endTimeOperator || endTimeOperator==''){ - endTimeOperator = endTimeOperator || '<=' - } - var theEndParameter = '`end`' - if(endIsStartTo){ - theEndParameter = '`time`' - } - switch(true){ - case(startTime && startTime !== '' && endTime && endTime !== ''): - queryString += ' AND `time` '+startTimeOperator+' ? AND '+theEndParameter+' '+endTimeOperator+' ?'; - queryStringCount += ' AND `time` '+startTimeOperator+' ? AND '+theEndParameter+' '+endTimeOperator+' ?'; - queryValues.push(startTime) - queryValues.push(endTime) - queryCountValues.push(startTime) - queryCountValues.push(endTime) - break; - case(startTime && startTime !== ''): - queryString += ' AND `time` '+startTimeOperator+' ?'; - queryStringCount += ' AND `time` '+startTimeOperator+' ?'; - queryValues.push(startTime) - queryCountValues.push(startTime) - break; - case(endTime && endTime !== ''): - queryString += ' AND '+theEndParameter+' '+endTimeOperator+' ?'; - queryStringCount += ' AND '+theEndParameter+' '+endTimeOperator+' ?'; - queryValues.push(endTime) - queryCountValues.push(endTime) - break; - } - } - queryString += ' ORDER BY `time` DESC'; - var rowLimit = limit || '100' - if(rowLimit !== '0'){ - queryString += ' LIMIT ' + rowLimit - } - s.sqlQuery(queryString,queryValues,function(err,r){ + const user = options.user + const groupKey = options.groupKey + const monitorId = options.monitorId + const archived = options.archived + const theTableSelected = options.table + const endIsStartTo = options.endIsStartTo + const userDetails = user.details + var endTime = options.endTime + var startTimeOperator = options.startTimeOperator + var endTimeOperator = options.endTimeOperator + var startTime = options.startTime + var limitString = `${options.limit}` + const monitorRestrictions = s.getMonitorRestrictions(options.user.details,monitorId) + getDatabaseRows({ + monitorRestrictions: monitorRestrictions, + table: theTableSelected, + groupKey: groupKey, + startDate: startTime, + endDate: endTime, + startOperator: startTimeOperator, + endOperator: endTimeOperator, + limit: options.limit, + archived: archived, + rowType: rowName, + endIsStartTo: endIsStartTo + },(response) => { + const limit = response.limit + const r = response[rowName]; if(!r){ callback({ total: 0, - limit: rowLimit, + limit: response.limit, skip: 0, [rowName]: [] }); @@ -521,22 +460,39 @@ module.exports = function(s,config){ }else{ callback({ ok: true, + limit: response.limit, [rowName]: r, endIsStartTo: endIsStartTo }) } }else{ - s.sqlQuery(queryStringCount,queryCountValues,function(err,count){ + getDatabaseRows({ + monitorRestrictions: monitorRestrictions, + columns: '*', + count: true, + table: theTableSelected, + groupKey: groupKey, + startDate: startTime, + endDate: endTime, + startOperator: startTimeOperator, + endOperator: endTimeOperator, + archived: archived, + type: 'count', + endIsStartTo: endIsStartTo + },(response) => { + console.log('count') + console.log(response) + const count = response.count var skipOver = 0 - if(rowLimit.indexOf(',') > -1){ - skipOver = parseInt(rowLimit.split(',')[0]) - rowLimit = parseInt(rowLimit.split(',')[1]) + if(limitString.indexOf(',') > -1){ + skipOver = parseInt(limitString.split(',')[0]) + limitString = parseInt(limitString.split(',')[1]) }else{ - rowLimit = parseInt(rowLimit) + limitString = parseInt(limitString) } callback({ - total: count[0]['COUNT(*)'], - limit: rowLimit, + total: response['count(*)'], + limit: response.limit, skip: skipOver, [rowName]: r, endIsStartTo: endIsStartTo diff --git a/libs/timelapse.js b/libs/timelapse.js index 35744be0..809e8949 100644 --- a/libs/timelapse.js +++ b/libs/timelapse.js @@ -169,7 +169,8 @@ module.exports = function(s,config,lang,app,io){ endOperator: req.query.endOperator, limit: req.query.limit, archived: req.query.archived, - type: 'frames' + rowType: 'frames', + endIsStartTo: true },(response) => { var isMp4Call = !!(req.query.mp4 || (req.params.date && typeof req.params.date === 'string' && req.params.date.indexOf('.') > -1)) if(isMp4Call && response.frames[0]){ diff --git a/libs/webServerSuperPaths.js b/libs/webServerSuperPaths.js index 0e64407c..fb80ffdf 100644 --- a/libs/webServerSuperPaths.js +++ b/libs/webServerSuperPaths.js @@ -26,6 +26,7 @@ module.exports = function(s,config,lang,app){ endOperator: req.query.endOperator, limit: req.query.limit, archived: req.query.archived, + endIsStartTo: true },(response) => { response.rows.forEach(function(v,n){ r[n].info = JSON.parse(v.info) From c42fbb85fd22a8de559ba9640db880af025725b2 Mon Sep 17 00:00:00 2001 From: Moe Date: Mon, 27 Jul 2020 18:22:12 -0700 Subject: [PATCH 046/175] sqlQuery Conversion : fix permissions for some endpoints --- libs/webServerPaths.js | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/libs/webServerPaths.js b/libs/webServerPaths.js index b88c863d..ebddc95b 100644 --- a/libs/webServerPaths.js +++ b/libs/webServerPaths.js @@ -847,7 +847,7 @@ module.exports = function(s,config,lang,app,io){ const groupKey = req.params.ke const monitorId = req.params.id const monitorRestrictions = s.getMonitorRestrictions(user.details,monitorId) - if(user.permissions.get_monitors === "0" || monitorRestrictions.length === 0){ + if(user.details.sub && (user.permissions.get_monitors === "0" || monitorRestrictions.length === 0)){ s.closeJsonResponse(res,[]); return } @@ -952,7 +952,7 @@ module.exports = function(s,config,lang,app,io){ const groupKey = req.params.ke const monitorId = req.params.id const monitorRestrictions = s.getMonitorRestrictions(user.details,monitorId) - if(user.permissions.get_monitors === "0" || monitorRestrictions.length === 0){ + if(user.details.sub && (user.permissions.get_monitors === "0" || monitorRestrictions.length === 0)){ s.closeJsonResponse(res,[]); return } @@ -965,7 +965,6 @@ module.exports = function(s,config,lang,app,io){ monitorRestrictions ] },(err,r) => { - console.log(r) r.forEach(function(v,n){ if(s.group[v.ke] && s.group[v.ke].activeMonitors[v.mid]){ r[n].currentlyWatching = Object.keys(s.group[v.ke].activeMonitors[v.mid].watch).length @@ -1220,7 +1219,7 @@ module.exports = function(s,config,lang,app,io){ const groupKey = req.params.ke const monitorId = req.params.id const monitorRestrictions = s.getMonitorRestrictions(user.details,monitorId) - if(user.permissions.get_monitors === "0" || monitorRestrictions.length === 0){ + if(user.details.sub && (user.permissions.get_monitors === "0" || monitorRestrictions.length === 0)){ s.closeJsonResponse(res,[]); return } @@ -1380,7 +1379,7 @@ module.exports = function(s,config,lang,app,io){ const groupKey = req.params.ke const monitorId = req.params.id const monitorRestrictions = s.getMonitorRestrictions(user.details,monitorId) - if(user.permissions.get_monitors === "0" || monitorRestrictions.length === 0){ + if(user.details.sub && (user.permissions.get_monitors === "0" || monitorRestrictions.length === 0)){ s.closeJsonResponse(res,[]); return } @@ -1413,7 +1412,7 @@ module.exports = function(s,config,lang,app,io){ const groupKey = req.params.ke const monitorId = req.params.id const monitorRestrictions = s.getMonitorRestrictions(user.details,monitorId) - if(user.permissions.get_monitors === "0" || monitorRestrictions.length === 0){ + if(user.details.sub && (user.permissions.get_monitors === "0" || monitorRestrictions.length === 0)){ s.closeJsonResponse(res,{ ok: false, msg: lang['Not Permitted'] @@ -1460,7 +1459,7 @@ module.exports = function(s,config,lang,app,io){ const groupKey = req.params.ke const monitorId = req.params.id const monitorRestrictions = s.getMonitorRestrictions(user.details,monitorId) - if(user.permissions.watch_videos === "0" || monitorRestrictions.length === 0){ + if(user.details.sub && (user.permissions.watch_videos === "0" || monitorRestrictions.length === 0)){ s.closeJsonResponse(res,{ ok: false, msg: lang['Not Permitted'] @@ -1509,7 +1508,7 @@ module.exports = function(s,config,lang,app,io){ const groupKey = req.params.ke const monitorId = req.params.id const monitorRestrictions = s.getMonitorRestrictions(user.details,monitorId) - if(user.permissions.watch_videos === "0" || monitorRestrictions.length === 0){ + if(user.details.sub && (user.permissions.watch_videos === "0" || monitorRestrictions.length === 0)){ s.closeJsonResponse(res,{ ok: false, msg: lang['Not Permitted'] From f523ccc2f2e02c1b9ea1dd936f9a950bb1ca053a Mon Sep 17 00:00:00 2001 From: Moe Date: Wed, 29 Jul 2020 11:00:30 -0700 Subject: [PATCH 047/175] Add Live GPS Display from Dashcam App (NinjaCam) --- libs/socketio.js | 9 +- web/libs/css/dash2.monitors.css | 11 + web/libs/js/dash2.elementbuilder.js | 1 + web/libs/js/dash2.socketio.js | 21 + web/libs/vendor/leaflet/images/layers-2x.png | Bin 0 -> 1259 bytes web/libs/vendor/leaflet/images/layers.png | Bin 0 -> 696 bytes .../vendor/leaflet/images/marker-icon-2x.png | Bin 0 -> 2464 bytes .../vendor/leaflet/images/marker-icon.png | Bin 0 -> 1466 bytes .../vendor/leaflet/images/marker-shadow.png | Bin 0 -> 618 bytes web/libs/vendor/leaflet/leaflet.css | 640 ++++++++++++++++++ web/libs/vendor/leaflet/leaflet.js | 5 + web/pages/home.ejs | 2 + 12 files changed, 688 insertions(+), 1 deletion(-) create mode 100755 web/libs/vendor/leaflet/images/layers-2x.png create mode 100755 web/libs/vendor/leaflet/images/layers.png create mode 100755 web/libs/vendor/leaflet/images/marker-icon-2x.png create mode 100755 web/libs/vendor/leaflet/images/marker-icon.png create mode 100755 web/libs/vendor/leaflet/images/marker-shadow.png create mode 100755 web/libs/vendor/leaflet/leaflet.css create mode 100755 web/libs/vendor/leaflet/leaflet.js diff --git a/libs/socketio.js b/libs/socketio.js index 1c4ac60e..dee7bd9c 100644 --- a/libs/socketio.js +++ b/libs/socketio.js @@ -1073,7 +1073,7 @@ module.exports = function(s,config,lang,io){ if(!s.group[d.ke].users)s.group[d.ke].users={}; if(!s.group[d.ke].dashcamUsers)s.group[d.ke].dashcamUsers={}; s.group[d.ke].users[d.auth]={ - cnid:cn.id, + cnid: cn.id, ke : d.ke, uid:r.uid, mail:r.mail, @@ -1127,6 +1127,13 @@ module.exports = function(s,config,lang,io){ } } }) + cn.on('gps',(d) => { + s.tx({ + f: 'gps', + gps: d.data, + mid: d.mid + },`MON_STREAM_${cn.ke}${d.mid}`) + }) //embed functions cn.on('e', function (d) { tx=function(z){if(!z.ke){z.ke=cn.ke;};cn.emit('f',z);} diff --git a/web/libs/css/dash2.monitors.css b/web/libs/css/dash2.monitors.css index 79535873..69b6e9d4 100644 --- a/web/libs/css/dash2.monitors.css +++ b/web/libs/css/dash2.monitors.css @@ -101,3 +101,14 @@ img.circle-img,div.circle-img{border-radius:50%;height:50px;width:50px} .stream-objects .stream-detected-object{position:absolute;top:0;left:0;border:3px solid red;background:transparent;border-radius:5px} .stream-objects .stream-detected-point{position:absolute;top:0;left:0;border:3px solid yellow;background:transparent;border-radius:5px} .stream-objects .point{position:absolute;top:0;left:0;border:3px solid red;border-radius:50%} + +.monitor_item .gps-map { + position: absolute; + width: 190px; + height: 190px; + border-radius: 5px; + border: 1px solid #333; + z-index: 9; + bottom: 10px; + right: 10px; +} diff --git a/web/libs/js/dash2.elementbuilder.js b/web/libs/js/dash2.elementbuilder.js index b9b6ca8b..d45229ef 100644 --- a/web/libs/js/dash2.elementbuilder.js +++ b/web/libs/js/dash2.elementbuilder.js @@ -100,6 +100,7 @@ $.ccio.tm=function(x,d,z,user){ k.mode=$.ccio.init('humanReadMode',d.mode); var dataTarget = '.monitor_item[mid=\''+d.mid+'\'][ke=\''+d.ke+'\'][auth=\''+user.auth_token+'\']'; tmp+='
'; + tmp+=''; tmp+='
'; tmp+='
'; tmp+='
' diff --git a/web/libs/js/dash2.socketio.js b/web/libs/js/dash2.socketio.js index 5b5f82bd..d9dd85ef 100644 --- a/web/libs/js/dash2.socketio.js +++ b/web/libs/js/dash2.socketio.js @@ -656,6 +656,27 @@ $.ccio.globalWebsocket=function(d,user){ $.ccio.init('jpegModeAll'); $('body').addClass('jpegMode') break; + case'gps': + var gps = d.gps + var mapBoxMarker = $.ccio.mon[user.ke + d.mid + user.auth_token].mapBoxMarker + $(`#gps-map-${d.mid}`).removeClass('hidden') + if(!mapBoxMarker){ + var mapBox = L.map(`gps-map-${d.mid}`).setView([gps.lat, gps.lng], 5); + + L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', { + attribution: 'OpenStreet Map' + }).addTo(mapBox); + + var mapBoxMarker = L.marker([gps.lat, gps.lng]).addTo(mapBox); + $.ccio.mon[user.ke + d.mid + user.auth_token].mapBoxMarker = mapBoxMarker + }else{ + mapBoxMarker.setLatLng([gps.lat, gps.lng]).update() + } + clearTimeout($.ccio.mon[user.ke + d.mid + user.auth_token].mapBoxTimeout) + $.ccio.mon[user.ke + d.mid + user.auth_token].mapBoxTimeout = setTimeout(function(){ + $(`#gps-map-${d.mid}`).addClass('hidden') + },30000) + break; } } if(location.search === '?assemble=1'){ diff --git a/web/libs/vendor/leaflet/images/layers-2x.png b/web/libs/vendor/leaflet/images/layers-2x.png new file mode 100755 index 0000000000000000000000000000000000000000..200c333dca9652ac4cba004d609e5af4eee168c1 GIT binary patch literal 1259 zcmVFhCYNy;#0irRPomHqW|G1C*;4?@4#E?jH>?v@U%cy?3dQAc-DchXVErpOh~ z-jbon+tNbnl6hoEb;)TVk+%hTDDi_G%i3*RZ&15!$Fjr^f;Ke&A@|?=`2&+{zr+3a z{D*=t(`AXyS%X7N z%a#RZw6vD^t_rnM`L4E>m=U&R!A-&}nZIi$BOPvkhrCuUe@BN~-lRD)f44;J%TwgE zcze8u!PQ_NR7?o(NylLXVTfDO zxs5=@|GsYEsNo4M#nT%N!UE(?dnS)t2+{ELYAFp*3=iF=|EQnTp`#vlSXuGVraYo? z+RCzXo6h3qA8{KG?S4nE(lM+;Eb4nT3XV;7gcAxUi5m)`k5tv}cPy()8ZR3TLW3I- zAS^}cq-IJvL7a4RgR!yk@~RT%$lA7{L5ES*hyx)M4(yxI$Ub(4f)K|^v1>zvwQY!_ zIrWw8q9GS^!Dp~}+?mbnB6jDF8mVlbQ!jFKDY;w=7;XO{9bq7>LXGK24WA`;rL)_Z z)&j}pbV(;6gY;VMhbxgvn`X;6x}VUEE-7 z%)7j-%t8S=ZL3yc)HbXDAqJZvBTPoiW_A-+a8m3_Z?v{DN7Tnr#O_VUMT0UBt$;p` zDh6JbGHN8JJ*JN%y2%msb97@_S>9!%Egwk;?PEkU9ntz&3uR}%Fj5d$JHQbQb3}a{ zSzFT^#n=VInPpcAS}CNxj?_ zVscANk5Cfz(51EI1pz};AWWb|kgbYNb4wCEGUn3+eMUMV?1-{=I4TlmLJMot@rd07 zZuo2hk1ccu{YmGkcYdWAVdk{Z4Nm?^cTD&}jGm+Q1SYIXMwmG*oO*83&#>l%nbR`G zhh=lZ%xIb7kU3#;TBbfECrnC9P=-XpL|TG2BoZdj61*XiFbW8?1Z_wp%#;>${SUIy V$8qr;L*)Pf002ovPDHLkV1hYLS~36t literal 0 HcmV?d00001 diff --git a/web/libs/vendor/leaflet/images/layers.png b/web/libs/vendor/leaflet/images/layers.png new file mode 100755 index 0000000000000000000000000000000000000000..1a72e5784b2b456eac5d7670738db80697af3377 GIT binary patch literal 696 zcmV;p0!RIcP)*@&l2<6p=!C&s@#ZL+%BQvF&b?w6S%wp=I>1QHj7AP5C)IWy#b znXXB;g;j=$a-tW89K%FbDceHVq&unY*Wx3L#=EGWH=rjqnp|4c_Ulec!ql3#G-5ZF zVlbBA@XP=)C8U&+Lrc)S4O5%1$&{(;7R^K(CSnvSr$v;+B$8q&7Bf|h$#PARo1^%M zf1H^nG-EiXVXr07OH(*8R)xa|FD;lXUlg_-%)~ZGsL2cX0NXaAzN2q%jqLRR6ruVk8`Jb7n#{`T;o@`F= z#3YcynIR^s83UNF3D!f5m#Mg)NJ24&Qfrqb&_z=yF;=B)#9Iq7u-@^O!(mW{D;qvr zPc)gVb%aowtS8m@ElL4A9G>w#ffQ~q{i&_i)*6f^)Sz|C?C>zb4Uo?H<-&Hz@a?J; z$ml@zGygWofb9$ZBj6aLjpLhsT2AzjOu=-*u_gSCUYnU^5s62$4H-fe}gSR(=wKRaTHh!@*b)YV6mo|a4Fn6Rgc&Rpk zvn_X|3VY?v=>nJ{slE^V1GaGWk}m@aIWGIpghbfPh8m@aIWEo_%AZI>==moIFVE^L=C zZJ91?mo03UEp3-BY?wBGur6$uD{Yr9Y?m%SHF8Fk1pc(Nva%QJ+{FLkalfypz3&M|||Fn`7|g3c~4(nXHKFmRnwn$J#_$xE8i z|Ns9!kC;(oC1qQk>LMp3_a2(odYyMT@>voX=UI)k>1cJdn;gjmJ-|6v4nb1Oryh)eQMwHP(i@!36%vGJyFK(JTj?Vb{{C=jx&)@1l zlFmnw%0`&bqruifkkHKC=vbiAM3&E`#Mv>2%tw;VK8?_|&E89cs{a1}$J*!f_xd-C z&F%B|oxRgPlh0F!txkxrQjNA`m9~?&&|jw4W0<`_iNHsX$VQXVK!B}Xkh4>av|f_8 zLY2?t?ejE=%(TnfV5iqOjm?d;&qI~ZGl|SzU77a)002XDQchC<95+*MjE@82?VLm= z3xf6%Vd@99z|q|-ua5l3kJxvZwan-8K1cPiwQAtlcNX~ZqLeoMB+a;7)WA|O#HOB% zg6SX;754xD1{Fy}K~#8Ntklac&zTpadXZ& zC*_=T&g7hfbI$R?v%9?sknIb97gJOJ=`-8YyS3ndqN+Jm+x33!p&Hc@@L$w))s2@N ztv~i}Emc?DykgwFWwma($8+~b>l?tqj$dh13R^nMZnva9 zn0Vflzv2Dvp`oVQw{Guby~i`JGbyBGTEC{y>yzCkg>K&CIeQ$u;lyQ+M{O~gEJ^)Z zrF3p)^>|uT;57}WY&IRwyOQ=dq%Az}_t=_hKowP!Z79q0;@Zu(SWEJJcHY+5T6I({ zw)wj*SNi4wrd+POUfZe4gF77vW?j zoFS}|r2n&$U9Y!S4VEOyN}OpZZi|?cr1VcE_tHsDQgp-ga(SwkBrkCm{|*-yb=}ZW zvcYvLvfA90TPn|!-TuYJV<6`}+RJeRgP3EA=qQcF9k0*#*{f&I_pjam%I6Dd#YE|G zqB!R}tW-K!wV1w+4JcFA_s6~=@9F&j8`u$-ifLN3vK;`lvaA-`jRn_}(8|)!3?-}I zvFi{H;@A$gEZYh?%|Qr_y#*UkOPjwiRCsJQ>mb6h5yGIk6C5_XA=8T?IBfm_?+P0; zhhUs)-(0R*H<&Kku(1>#cGtOpk&Z&kQcw&SJv-4VY<+;=8hYnoX zfNJMCa9)^5Z0;2dCUk;x-%#yS!I~Jr3pNuI!g_tHz!$hKwt1GL~sFvx)3u4TA zv>CLGdQtoZ7Du7ctJRfTqY;FPxs1G{ZJ?73D5J@OO{6BHcPbk{_mjg&p2QFeke%QI zlAJ-kvjuwy1<5D-6>su68A+i998aSZNnQX)+Q}6(GK-C%8G-!1bOJBONU{gT%IOOE z;Yk24YC@^lFW77>r6x7eS1Omc;8=GUp#&zLQ&L{ zv8$hGC`wp~$9pR>f%-_Ps3>YhzP(+vC(E*zr1CVO8ChN^MI-VGMX7+|(r!SGZ9gd5 zzO9sQd>sm|f1|X&oh=8lOzd6+ITvo zCXInR?>RZ#>Hb*PO=7dI!dZ(wY4O}ZGv zdfQFio7+0~PN*RFCZGM6@9-o~y*@?;k00NvOsw54t1^tt{*ATMs^2j}4Wp=4t3RH* z_+8b`F-{E=0sOgM<;VHTo!Ij3u zmmI`2?K7g(GOcGA)@h?$SW&pwHdtj1n57PLI8&6RHhx4R%Q7b z^JEqR)@06V!pbS*@D_ZyRMo_LlT}r{#sXOx4kM-V<_V{!5SSuM^SIVCA37|nY7LWQ zZA#B1h4l`6asz=Lvax_#GMRX|NF>=$=p{Qn0i@ExX1jGhy@B8a*_uR+ODEbVi8ObL zezG?azy>E~S~dl43&8<$(2H}P&*tuBdESUP83KQ?8B z?K(!uS>H1wlWQz;qOfB`T#TZ=EoSp~vZ5XtCvwm1h*Ex6mzTsn_y@_=xREIslV-%- zpdWkEzMjeNOGWrSM32gpBt27*O29NdhGzuDgYxcf`Jjjqw@B;Vmdb@fxdhCRi`Kg> zmUTr$=&@#i!%F4Q6mb&4QKfR^95KJ!<6~fqx-f^66AV!|ywG{6D^Vay-3b99>XOe# e-I|>x8~*?ZhF3snGbtJX0000cOl4 literal 0 HcmV?d00001 diff --git a/web/libs/vendor/leaflet/images/marker-icon.png b/web/libs/vendor/leaflet/images/marker-icon.png new file mode 100755 index 0000000000000000000000000000000000000000..950edf24677ded147df13b26f91baa2b0fa70513 GIT binary patch literal 1466 zcmV;r1x5OaP)P001cn1^@s6z>|W`000GnNklGNuHDcIX17Zdjl&3`L?0sTjIws<{((Dh&g-s0<@jYQyl?D*X^?%13;ml^gy> ziMrY_^1WI=(g@LMizu=zCoA>C`6|QEq1eV92k*7m>G65*&@&6)aC&e}G zI)pf-Za|N`DT&Cn1J|o`19mumxW~hiKiKyc-P`S@q)rdTo84@QI@;0yXrG%9uhI>A zG5QHb6s4=<6xy{1 z@NMxEkryp{LS44%z$3lP^cX!9+2-;CTt3wM4(k*#C{aiIiLuB>jJj;KPhPzIC00bL zU3a#;aJld94lCW=`4&aAy8M7PY=HQ>O%$YEP4c4UY#CRxfgbE~(|uiI=YS8q;O9y6 zmIkXzR`}p7ti|PrM3a}WMnR=3NVnWdAAR>b9X@)DKL6=YsvmH%?I24wdq?Gh54_;# z$?_LvgjEdspdQlft#4CQ z`2Zyvy?*)N1Ftw|{_hakhG9WjS?Az@I@+IZ8JbWewR!XUK4&6346+d#~gsE0SY(LX8&JfY>Aj)RxGy96nwhs2rv zzW6pTnMpFkDSkT*a*6Dx|u@ds6ISVn0@^RmIsKZ5Y;bazbc;tTSq(kg(=481ODrPyNB6n z-$+U}(w$m6U6H$w17Bw+wDaFIe~GvNMYvnw31MpY0eQKT9l>SU``8k7w4)z!GZKMI z#_cEKq7k~i%nlK@6c-K?+R;B#5$?T#YpKD`t_4bAs^#E+@5QW$@OX3*`;(#{U^d-vY)&xEE>n5lYl&T?Amke9$Lam@{1K@O ze*LXqlKQHiv=gx+V^Cbb2?z@ISBQ*3amF;9UJ3SBg(N|710TLamQmYZ&Qjn2LuO<* zCZlB4n%@pc&7NNnY1}x+NWpHlq`OJEo|`aYN9<`RBUB+79g;>dgb6YlfN#kGL?lO_ z!6~M^7sOnbsUkKk<@Ysie&`G>ruxH&Mgy&8;i=A zB9OO!xR{AyODw>DS-q5YM{0ExFEAzt zm>RdS+ssW(-8|?xr0(?$vBVB*%(xDLtq3Hf0I5yFm<_g=W2`QWAax{1rWVH=I!VrP zs(rTFX@W#t$hXNvbgX`gK&^w_YD;CQ!B@e0QbLIWaKAXQe2-kkloo;{iF#6}z!4=W zi$giRj1{ zt;2w`VSCF#WE&*ev7jpsC=6175@(~nTE2;7M-L((0bH@yG}-TB$R~WXd?tA$s3|%y zA`9$sA(>F%J3ioz<-LJl*^o1|w84l>HBR`>3l9c8$5Xr@xCiIQ7{x$fMCzOk_-M=% z+{a_Q#;42`#KfUte@$NT77uaTz?b-fBe)1s5XE$yA79fm?KqM^VgLXD07*qoM6N<$ Ef<_J(9smFU literal 0 HcmV?d00001 diff --git a/web/libs/vendor/leaflet/leaflet.css b/web/libs/vendor/leaflet/leaflet.css new file mode 100755 index 00000000..601476fe --- /dev/null +++ b/web/libs/vendor/leaflet/leaflet.css @@ -0,0 +1,640 @@ +/* required styles */ + +.leaflet-pane, +.leaflet-tile, +.leaflet-marker-icon, +.leaflet-marker-shadow, +.leaflet-tile-container, +.leaflet-pane > svg, +.leaflet-pane > canvas, +.leaflet-zoom-box, +.leaflet-image-layer, +.leaflet-layer { + position: absolute; + left: 0; + top: 0; + } +.leaflet-container { + overflow: hidden; + } +.leaflet-tile, +.leaflet-marker-icon, +.leaflet-marker-shadow { + -webkit-user-select: none; + -moz-user-select: none; + user-select: none; + -webkit-user-drag: none; + } +/* Prevents IE11 from highlighting tiles in blue */ +.leaflet-tile::selection { + background: transparent; +} +/* Safari renders non-retina tile on retina better with this, but Chrome is worse */ +.leaflet-safari .leaflet-tile { + image-rendering: -webkit-optimize-contrast; + } +/* hack that prevents hw layers "stretching" when loading new tiles */ +.leaflet-safari .leaflet-tile-container { + width: 1600px; + height: 1600px; + -webkit-transform-origin: 0 0; + } +.leaflet-marker-icon, +.leaflet-marker-shadow { + display: block; + } +/* .leaflet-container svg: reset svg max-width decleration shipped in Joomla! (joomla.org) 3.x */ +/* .leaflet-container img: map is broken in FF if you have max-width: 100% on tiles */ +.leaflet-container .leaflet-overlay-pane svg, +.leaflet-container .leaflet-marker-pane img, +.leaflet-container .leaflet-shadow-pane img, +.leaflet-container .leaflet-tile-pane img, +.leaflet-container img.leaflet-image-layer, +.leaflet-container .leaflet-tile { + max-width: none !important; + max-height: none !important; + } + +.leaflet-container.leaflet-touch-zoom { + -ms-touch-action: pan-x pan-y; + touch-action: pan-x pan-y; + } +.leaflet-container.leaflet-touch-drag { + -ms-touch-action: pinch-zoom; + /* Fallback for FF which doesn't support pinch-zoom */ + touch-action: none; + touch-action: pinch-zoom; +} +.leaflet-container.leaflet-touch-drag.leaflet-touch-zoom { + -ms-touch-action: none; + touch-action: none; +} +.leaflet-container { + -webkit-tap-highlight-color: transparent; +} +.leaflet-container a { + -webkit-tap-highlight-color: rgba(51, 181, 229, 0.4); +} +.leaflet-tile { + filter: inherit; + visibility: hidden; + } +.leaflet-tile-loaded { + visibility: inherit; + } +.leaflet-zoom-box { + width: 0; + height: 0; + -moz-box-sizing: border-box; + box-sizing: border-box; + z-index: 800; + } +/* workaround for https://bugzilla.mozilla.org/show_bug.cgi?id=888319 */ +.leaflet-overlay-pane svg { + -moz-user-select: none; + } + +.leaflet-pane { z-index: 400; } + +.leaflet-tile-pane { z-index: 200; } +.leaflet-overlay-pane { z-index: 400; } +.leaflet-shadow-pane { z-index: 500; } +.leaflet-marker-pane { z-index: 600; } +.leaflet-tooltip-pane { z-index: 650; } +.leaflet-popup-pane { z-index: 700; } + +.leaflet-map-pane canvas { z-index: 100; } +.leaflet-map-pane svg { z-index: 200; } + +.leaflet-vml-shape { + width: 1px; + height: 1px; + } +.lvml { + behavior: url(#default#VML); + display: inline-block; + position: absolute; + } + + +/* control positioning */ + +.leaflet-control { + position: relative; + z-index: 800; + pointer-events: visiblePainted; /* IE 9-10 doesn't have auto */ + pointer-events: auto; + } +.leaflet-top, +.leaflet-bottom { + position: absolute; + z-index: 1000; + pointer-events: none; + } +.leaflet-top { + top: 0; + } +.leaflet-right { + right: 0; + } +.leaflet-bottom { + bottom: 0; + } +.leaflet-left { + left: 0; + } +.leaflet-control { + float: left; + clear: both; + } +.leaflet-right .leaflet-control { + float: right; + } +.leaflet-top .leaflet-control { + margin-top: 10px; + } +.leaflet-bottom .leaflet-control { + margin-bottom: 10px; + } +.leaflet-left .leaflet-control { + margin-left: 10px; + } +.leaflet-right .leaflet-control { + margin-right: 10px; + } + + +/* zoom and fade animations */ + +.leaflet-fade-anim .leaflet-tile { + will-change: opacity; + } +.leaflet-fade-anim .leaflet-popup { + opacity: 0; + -webkit-transition: opacity 0.2s linear; + -moz-transition: opacity 0.2s linear; + transition: opacity 0.2s linear; + } +.leaflet-fade-anim .leaflet-map-pane .leaflet-popup { + opacity: 1; + } +.leaflet-zoom-animated { + -webkit-transform-origin: 0 0; + -ms-transform-origin: 0 0; + transform-origin: 0 0; + } +.leaflet-zoom-anim .leaflet-zoom-animated { + will-change: transform; + } +.leaflet-zoom-anim .leaflet-zoom-animated { + -webkit-transition: -webkit-transform 0.25s cubic-bezier(0,0,0.25,1); + -moz-transition: -moz-transform 0.25s cubic-bezier(0,0,0.25,1); + transition: transform 0.25s cubic-bezier(0,0,0.25,1); + } +.leaflet-zoom-anim .leaflet-tile, +.leaflet-pan-anim .leaflet-tile { + -webkit-transition: none; + -moz-transition: none; + transition: none; + } + +.leaflet-zoom-anim .leaflet-zoom-hide { + visibility: hidden; + } + + +/* cursors */ + +.leaflet-interactive { + cursor: pointer; + } +.leaflet-grab { + cursor: -webkit-grab; + cursor: -moz-grab; + cursor: grab; + } +.leaflet-crosshair, +.leaflet-crosshair .leaflet-interactive { + cursor: crosshair; + } +.leaflet-popup-pane, +.leaflet-control { + cursor: auto; + } +.leaflet-dragging .leaflet-grab, +.leaflet-dragging .leaflet-grab .leaflet-interactive, +.leaflet-dragging .leaflet-marker-draggable { + cursor: move; + cursor: -webkit-grabbing; + cursor: -moz-grabbing; + cursor: grabbing; + } + +/* marker & overlays interactivity */ +.leaflet-marker-icon, +.leaflet-marker-shadow, +.leaflet-image-layer, +.leaflet-pane > svg path, +.leaflet-tile-container { + pointer-events: none; + } + +.leaflet-marker-icon.leaflet-interactive, +.leaflet-image-layer.leaflet-interactive, +.leaflet-pane > svg path.leaflet-interactive, +svg.leaflet-image-layer.leaflet-interactive path { + pointer-events: visiblePainted; /* IE 9-10 doesn't have auto */ + pointer-events: auto; + } + +/* visual tweaks */ + +.leaflet-container { + background: #ddd; + outline: 0; + } +.leaflet-container a { + color: #0078A8; + } +.leaflet-container a.leaflet-active { + outline: 2px solid orange; + } +.leaflet-zoom-box { + border: 2px dotted #38f; + background: rgba(255,255,255,0.5); + } + + +/* general typography */ +.leaflet-container { + font: 12px/1.5 "Helvetica Neue", Arial, Helvetica, sans-serif; + } + + +/* general toolbar styles */ + +.leaflet-bar { + box-shadow: 0 1px 5px rgba(0,0,0,0.65); + border-radius: 4px; + } +.leaflet-bar a, +.leaflet-bar a:hover { + background-color: #fff; + border-bottom: 1px solid #ccc; + width: 26px; + height: 26px; + line-height: 26px; + display: block; + text-align: center; + text-decoration: none; + color: black; + } +.leaflet-bar a, +.leaflet-control-layers-toggle { + background-position: 50% 50%; + background-repeat: no-repeat; + display: block; + } +.leaflet-bar a:hover { + background-color: #f4f4f4; + } +.leaflet-bar a:first-child { + border-top-left-radius: 4px; + border-top-right-radius: 4px; + } +.leaflet-bar a:last-child { + border-bottom-left-radius: 4px; + border-bottom-right-radius: 4px; + border-bottom: none; + } +.leaflet-bar a.leaflet-disabled { + cursor: default; + background-color: #f4f4f4; + color: #bbb; + } + +.leaflet-touch .leaflet-bar a { + width: 30px; + height: 30px; + line-height: 30px; + } +.leaflet-touch .leaflet-bar a:first-child { + border-top-left-radius: 2px; + border-top-right-radius: 2px; + } +.leaflet-touch .leaflet-bar a:last-child { + border-bottom-left-radius: 2px; + border-bottom-right-radius: 2px; + } + +/* zoom control */ + +.leaflet-control-zoom-in, +.leaflet-control-zoom-out { + font: bold 18px 'Lucida Console', Monaco, monospace; + text-indent: 1px; + } + +.leaflet-touch .leaflet-control-zoom-in, .leaflet-touch .leaflet-control-zoom-out { + font-size: 22px; + } + + +/* layers control */ + +.leaflet-control-layers { + box-shadow: 0 1px 5px rgba(0,0,0,0.4); + background: #fff; + border-radius: 5px; + } +.leaflet-control-layers-toggle { + background-image: url(images/layers.png); + width: 36px; + height: 36px; + } +.leaflet-retina .leaflet-control-layers-toggle { + background-image: url(images/layers-2x.png); + background-size: 26px 26px; + } +.leaflet-touch .leaflet-control-layers-toggle { + width: 44px; + height: 44px; + } +.leaflet-control-layers .leaflet-control-layers-list, +.leaflet-control-layers-expanded .leaflet-control-layers-toggle { + display: none; + } +.leaflet-control-layers-expanded .leaflet-control-layers-list { + display: block; + position: relative; + } +.leaflet-control-layers-expanded { + padding: 6px 10px 6px 6px; + color: #333; + background: #fff; + } +.leaflet-control-layers-scrollbar { + overflow-y: scroll; + overflow-x: hidden; + padding-right: 5px; + } +.leaflet-control-layers-selector { + margin-top: 2px; + position: relative; + top: 1px; + } +.leaflet-control-layers label { + display: block; + } +.leaflet-control-layers-separator { + height: 0; + border-top: 1px solid #ddd; + margin: 5px -10px 5px -6px; + } + +/* Default icon URLs */ +.leaflet-default-icon-path { + background-image: url(images/marker-icon.png); + } + + +/* attribution and scale controls */ + +.leaflet-container .leaflet-control-attribution { + background: #fff; + background: rgba(255, 255, 255, 0.7); + margin: 0; + } +.leaflet-control-attribution, +.leaflet-control-scale-line { + padding: 0 5px; + color: #333; + } +.leaflet-control-attribution a { + text-decoration: none; + } +.leaflet-control-attribution a:hover { + text-decoration: underline; + } +.leaflet-container .leaflet-control-attribution, +.leaflet-container .leaflet-control-scale { + font-size: 11px; + } +.leaflet-left .leaflet-control-scale { + margin-left: 5px; + } +.leaflet-bottom .leaflet-control-scale { + margin-bottom: 5px; + } +.leaflet-control-scale-line { + border: 2px solid #777; + border-top: none; + line-height: 1.1; + padding: 2px 5px 1px; + font-size: 11px; + white-space: nowrap; + overflow: hidden; + -moz-box-sizing: border-box; + box-sizing: border-box; + + background: #fff; + background: rgba(255, 255, 255, 0.5); + } +.leaflet-control-scale-line:not(:first-child) { + border-top: 2px solid #777; + border-bottom: none; + margin-top: -2px; + } +.leaflet-control-scale-line:not(:first-child):not(:last-child) { + border-bottom: 2px solid #777; + } + +.leaflet-touch .leaflet-control-attribution, +.leaflet-touch .leaflet-control-layers, +.leaflet-touch .leaflet-bar { + box-shadow: none; + } +.leaflet-touch .leaflet-control-layers, +.leaflet-touch .leaflet-bar { + border: 2px solid rgba(0,0,0,0.2); + background-clip: padding-box; + } + + +/* popup */ + +.leaflet-popup { + position: absolute; + text-align: center; + margin-bottom: 20px; + } +.leaflet-popup-content-wrapper { + padding: 1px; + text-align: left; + border-radius: 12px; + } +.leaflet-popup-content { + margin: 13px 19px; + line-height: 1.4; + } +.leaflet-popup-content p { + margin: 18px 0; + } +.leaflet-popup-tip-container { + width: 40px; + height: 20px; + position: absolute; + left: 50%; + margin-left: -20px; + overflow: hidden; + pointer-events: none; + } +.leaflet-popup-tip { + width: 17px; + height: 17px; + padding: 1px; + + margin: -10px auto 0; + + -webkit-transform: rotate(45deg); + -moz-transform: rotate(45deg); + -ms-transform: rotate(45deg); + transform: rotate(45deg); + } +.leaflet-popup-content-wrapper, +.leaflet-popup-tip { + background: white; + color: #333; + box-shadow: 0 3px 14px rgba(0,0,0,0.4); + } +.leaflet-container a.leaflet-popup-close-button { + position: absolute; + top: 0; + right: 0; + padding: 4px 4px 0 0; + border: none; + text-align: center; + width: 18px; + height: 14px; + font: 16px/14px Tahoma, Verdana, sans-serif; + color: #c3c3c3; + text-decoration: none; + font-weight: bold; + background: transparent; + } +.leaflet-container a.leaflet-popup-close-button:hover { + color: #999; + } +.leaflet-popup-scrolled { + overflow: auto; + border-bottom: 1px solid #ddd; + border-top: 1px solid #ddd; + } + +.leaflet-oldie .leaflet-popup-content-wrapper { + -ms-zoom: 1; + } +.leaflet-oldie .leaflet-popup-tip { + width: 24px; + margin: 0 auto; + + -ms-filter: "progid:DXImageTransform.Microsoft.Matrix(M11=0.70710678, M12=0.70710678, M21=-0.70710678, M22=0.70710678)"; + filter: progid:DXImageTransform.Microsoft.Matrix(M11=0.70710678, M12=0.70710678, M21=-0.70710678, M22=0.70710678); + } +.leaflet-oldie .leaflet-popup-tip-container { + margin-top: -1px; + } + +.leaflet-oldie .leaflet-control-zoom, +.leaflet-oldie .leaflet-control-layers, +.leaflet-oldie .leaflet-popup-content-wrapper, +.leaflet-oldie .leaflet-popup-tip { + border: 1px solid #999; + } + + +/* div icon */ + +.leaflet-div-icon { + background: #fff; + border: 1px solid #666; + } + + +/* Tooltip */ +/* Base styles for the element that has a tooltip */ +.leaflet-tooltip { + position: absolute; + padding: 6px; + background-color: #fff; + border: 1px solid #fff; + border-radius: 3px; + color: #222; + white-space: nowrap; + -webkit-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; + pointer-events: none; + box-shadow: 0 1px 3px rgba(0,0,0,0.4); + } +.leaflet-tooltip.leaflet-clickable { + cursor: pointer; + pointer-events: auto; + } +.leaflet-tooltip-top:before, +.leaflet-tooltip-bottom:before, +.leaflet-tooltip-left:before, +.leaflet-tooltip-right:before { + position: absolute; + pointer-events: none; + border: 6px solid transparent; + background: transparent; + content: ""; + } + +/* Directions */ + +.leaflet-tooltip-bottom { + margin-top: 6px; +} +.leaflet-tooltip-top { + margin-top: -6px; +} +.leaflet-tooltip-bottom:before, +.leaflet-tooltip-top:before { + left: 50%; + margin-left: -6px; + } +.leaflet-tooltip-top:before { + bottom: 0; + margin-bottom: -12px; + border-top-color: #fff; + } +.leaflet-tooltip-bottom:before { + top: 0; + margin-top: -12px; + margin-left: -6px; + border-bottom-color: #fff; + } +.leaflet-tooltip-left { + margin-left: -6px; +} +.leaflet-tooltip-right { + margin-left: 6px; +} +.leaflet-tooltip-left:before, +.leaflet-tooltip-right:before { + top: 50%; + margin-top: -6px; + } +.leaflet-tooltip-left:before { + right: 0; + margin-right: -12px; + border-left-color: #fff; + } +.leaflet-tooltip-right:before { + left: 0; + margin-left: -12px; + border-right-color: #fff; + } diff --git a/web/libs/vendor/leaflet/leaflet.js b/web/libs/vendor/leaflet/leaflet.js new file mode 100755 index 00000000..13e8b1e0 --- /dev/null +++ b/web/libs/vendor/leaflet/leaflet.js @@ -0,0 +1,5 @@ +/* @preserve + * Leaflet 1.6.0, a JS library for interactive maps. http://leafletjs.com + * (c) 2010-2019 Vladimir Agafonkin, (c) 2010-2011 CloudMade + */ +!function(t,i){"object"==typeof exports&&"undefined"!=typeof module?i(exports):"function"==typeof define&&define.amd?define(["exports"],i):i(t.L={})}(this,function(t){"use strict";var i=Object.freeze;function h(t){var i,e,n,o;for(e=1,n=arguments.length;e=this.min.x&&e.x<=this.max.x&&i.y>=this.min.y&&e.y<=this.max.y},intersects:function(t){t=R(t);var i=this.min,e=this.max,n=t.min,o=t.max,s=o.x>=i.x&&n.x<=e.x,r=o.y>=i.y&&n.y<=e.y;return s&&r},overlaps:function(t){t=R(t);var i=this.min,e=this.max,n=t.min,o=t.max,s=o.x>i.x&&n.xi.y&&n.y=n.lat&&e.lat<=o.lat&&i.lng>=n.lng&&e.lng<=o.lng},intersects:function(t){t=D(t);var i=this._southWest,e=this._northEast,n=t.getSouthWest(),o=t.getNorthEast(),s=o.lat>=i.lat&&n.lat<=e.lat,r=o.lng>=i.lng&&n.lng<=e.lng;return s&&r},overlaps:function(t){t=D(t);var i=this._southWest,e=this._northEast,n=t.getSouthWest(),o=t.getNorthEast(),s=o.lat>i.lat&&n.lati.lng&&n.lng';var i=t.firstChild;return i.style.behavior="url(#default#VML)",i&&"object"==typeof i.adj}catch(t){return!1}}();function Bt(t){return 0<=navigator.userAgent.toLowerCase().indexOf(t)}var At=(Object.freeze||Object)({ie:it,ielt9:et,edge:nt,webkit:ot,android:st,android23:rt,androidStock:ht,opera:ut,chrome:lt,gecko:ct,safari:_t,phantom:dt,opera12:pt,win:mt,ie3d:ft,webkit3d:gt,gecko3d:vt,any3d:yt,mobile:xt,mobileWebkit:wt,mobileWebkit3d:Pt,msPointer:Lt,pointer:bt,touch:Tt,mobileOpera:zt,mobileGecko:Mt,retina:Ct,passiveEvents:St,canvas:Et,svg:Zt,vml:kt}),It=Lt?"MSPointerDown":"pointerdown",Ot=Lt?"MSPointerMove":"pointermove",Rt=Lt?"MSPointerUp":"pointerup",Nt=Lt?"MSPointerCancel":"pointercancel",Dt=["INPUT","SELECT","OPTION"],jt={},Wt=!1,Ht=0;function Ft(t,i,e,n){return"touchstart"===i?function(t,i,e){var n=a(function(t){if("mouse"!==t.pointerType&&t.MSPOINTER_TYPE_MOUSE&&t.pointerType!==t.MSPOINTER_TYPE_MOUSE){if(!(Dt.indexOf(t.target.tagName)<0))return;ji(t)}Gt(t,i)});t["_leaflet_touchstart"+e]=n,t.addEventListener(It,n,!1),Wt||(document.documentElement.addEventListener(It,Ut,!0),document.documentElement.addEventListener(Ot,Vt,!0),document.documentElement.addEventListener(Rt,qt,!0),document.documentElement.addEventListener(Nt,qt,!0),Wt=!0)}(t,e,n):"touchmove"===i?function(t,i,e){function n(t){(t.pointerType!==t.MSPOINTER_TYPE_MOUSE&&"mouse"!==t.pointerType||0!==t.buttons)&&Gt(t,i)}t["_leaflet_touchmove"+e]=n,t.addEventListener(Ot,n,!1)}(t,e,n):"touchend"===i&&function(t,i,e){function n(t){Gt(t,i)}t["_leaflet_touchend"+e]=n,t.addEventListener(Rt,n,!1),t.addEventListener(Nt,n,!1)}(t,e,n),this}function Ut(t){jt[t.pointerId]=t,Ht++}function Vt(t){jt[t.pointerId]&&(jt[t.pointerId]=t)}function qt(t){delete jt[t.pointerId],Ht--}function Gt(t,i){for(var e in t.touches=[],jt)t.touches.push(jt[e]);t.changedTouches=[t],i(t)}var Kt=Lt?"MSPointerDown":bt?"pointerdown":"touchstart",Yt=Lt?"MSPointerUp":bt?"pointerup":"touchend",Xt="_leaflet_";function Jt(t,o,i){var s,r,a=!1;function e(t){var i;if(bt){if(!nt||"mouse"===t.pointerType)return;i=Ht}else i=t.touches.length;if(!(1this.options.maxZoom)?this.setZoom(t):this},panInsideBounds:function(t,i){this._enforcingBounds=!0;var e=this.getCenter(),n=this._limitCenter(e,this._zoom,D(t));return e.equals(n)||this.panTo(n,i),this._enforcingBounds=!1,this},panInside:function(t,i){var e=I((i=i||{}).paddingTopLeft||i.padding||[0,0]),n=I(i.paddingBottomRight||i.padding||[0,0]),o=this.getCenter(),s=this.project(o),r=this.project(t),a=this.getPixelBounds(),h=a.getSize().divideBy(2),u=R([a.min.add(e),a.max.subtract(n)]);if(!u.contains(r)){this._enforcingBounds=!0;var l=s.subtract(r),c=I(r.x+l.x,r.y+l.y);(r.xu.max.x)&&(c.x=s.x-l.x,0u.max.y)&&(c.y=s.y-l.y,0=this.options.transform3DLimit&&this._resetView(this.getCenter(),this.getZoom())},_findEventTargets:function(t,i){for(var e,n=[],o="mouseout"===i||"mouseover"===i,s=t.target||t.srcElement,r=!1;s;){if((e=this._targets[u(s)])&&("click"===i||"preclick"===i)&&!t._simulated&&this._draggableMoved(e)){r=!0;break}if(e&&e.listens(i,!0)){if(o&&!Yi(s,t))break;if(n.push(e),o)break}if(s===this._container)break;s=s.parentNode}return n.length||r||o||!Yi(s,t)||(n=[this]),n},_handleDOMEvent:function(t){if(this._loaded&&!Ki(t)){var i=t.type;"mousedown"!==i&&"keypress"!==i&&"keyup"!==i&&"keydown"!==i||Mi(t.target||t.srcElement),this._fireDOMEvent(t,i)}},_mouseEvents:["click","dblclick","mouseover","mouseout","contextmenu"],_fireDOMEvent:function(t,i,e){if("click"===t.type){var n=h({},t);n.type="preclick",this._fireDOMEvent(n,n.type,e)}if(!t._stopped&&(e=(e||[]).concat(this._findEventTargets(t,i))).length){var o=e[0];"contextmenu"===i&&o.listens(i,!0)&&ji(t);var s={originalEvent:t};if("keypress"!==t.type&&"keydown"!==t.type&&"keyup"!==t.type){var r=o.getLatLng&&(!o._radius||o._radius<=10);s.containerPoint=r?this.latLngToContainerPoint(o.getLatLng()):this.mouseEventToContainerPoint(t),s.layerPoint=this.containerPointToLayerPoint(s.containerPoint),s.latlng=r?o.getLatLng():this.layerPointToLatLng(s.layerPoint)}for(var a=0;athis.options.zoomAnimationThreshold)return!1;var n=this.getZoomScale(i),o=this._getCenterOffset(t)._divideBy(1-1/n);return!(!0!==e.animate&&!this.getSize().contains(o))&&(M(function(){this._moveStart(!0,!1)._animateZoom(t,i,!0)},this),!0)},_animateZoom:function(t,i,e,n){this._mapPane&&(e&&(this._animatingZoom=!0,this._animateToCenter=t,this._animateToZoom=i,mi(this._mapPane,"leaflet-zoom-anim")),this.fire("zoomanim",{center:t,zoom:i,noUpdate:n}),setTimeout(a(this._onZoomTransitionEnd,this),250))},_onZoomTransitionEnd:function(){this._animatingZoom&&(this._mapPane&&fi(this._mapPane,"leaflet-zoom-anim"),this._animatingZoom=!1,this._move(this._animateToCenter,this._animateToZoom),M(function(){this._moveEnd(!0)},this))}});function Qi(t){return new te(t)}var te=E.extend({options:{position:"topright"},initialize:function(t){p(this,t)},getPosition:function(){return this.options.position},setPosition:function(t){var i=this._map;return i&&i.removeControl(this),this.options.position=t,i&&i.addControl(this),this},getContainer:function(){return this._container},addTo:function(t){this.remove(),this._map=t;var i=this._container=this.onAdd(t),e=this.getPosition(),n=t._controlCorners[e];return mi(i,"leaflet-control"),-1!==e.indexOf("bottom")?n.insertBefore(i,n.firstChild):n.appendChild(i),this._map.on("unload",this.remove,this),this},remove:function(){return this._map&&(li(this._container),this.onRemove&&this.onRemove(this._map),this._map.off("unload",this.remove,this),this._map=null),this},_refocusOnMap:function(t){this._map&&t&&0",n=document.createElement("div");return n.innerHTML=e,n.firstChild},_addItem:function(t){var i,e=document.createElement("label"),n=this._map.hasLayer(t.layer);t.overlay?((i=document.createElement("input")).type="checkbox",i.className="leaflet-control-layers-selector",i.defaultChecked=n):i=this._createRadioElement("leaflet-base-layers_"+u(this),n),this._layerControlInputs.push(i),i.layerId=u(t.layer),ki(i,"click",this._onInputClick,this);var o=document.createElement("span");o.innerHTML=" "+t.name;var s=document.createElement("div");return e.appendChild(s),s.appendChild(i),s.appendChild(o),(t.overlay?this._overlaysList:this._baseLayersList).appendChild(e),this._checkDisabledLayers(),e},_onInputClick:function(){var t,i,e=this._layerControlInputs,n=[],o=[];this._handlingClick=!0;for(var s=e.length-1;0<=s;s--)t=e[s],i=this._getLayer(t.layerId).layer,t.checked?n.push(i):t.checked||o.push(i);for(s=0;si.options.maxZoom},_expandIfNotCollapsed:function(){return this._map&&!this.options.collapsed&&this.expand(),this},_expand:function(){return this.expand()},_collapse:function(){return this.collapse()}}),ee=te.extend({options:{position:"topleft",zoomInText:"+",zoomInTitle:"Zoom in",zoomOutText:"−",zoomOutTitle:"Zoom out"},onAdd:function(t){var i="leaflet-control-zoom",e=ui("div",i+" leaflet-bar"),n=this.options;return this._zoomInButton=this._createButton(n.zoomInText,n.zoomInTitle,i+"-in",e,this._zoomIn),this._zoomOutButton=this._createButton(n.zoomOutText,n.zoomOutTitle,i+"-out",e,this._zoomOut),this._updateDisabled(),t.on("zoomend zoomlevelschange",this._updateDisabled,this),e},onRemove:function(t){t.off("zoomend zoomlevelschange",this._updateDisabled,this)},disable:function(){return this._disabled=!0,this._updateDisabled(),this},enable:function(){return this._disabled=!1,this._updateDisabled(),this},_zoomIn:function(t){!this._disabled&&this._map._zoomthis._map.getMinZoom()&&this._map.zoomOut(this._map.options.zoomDelta*(t.shiftKey?3:1))},_createButton:function(t,i,e,n,o){var s=ui("a",e,n);return s.innerHTML=t,s.href="#",s.title=i,s.setAttribute("role","button"),s.setAttribute("aria-label",i),Di(s),ki(s,"click",Wi),ki(s,"click",o,this),ki(s,"click",this._refocusOnMap,this),s},_updateDisabled:function(){var t=this._map,i="leaflet-disabled";fi(this._zoomInButton,i),fi(this._zoomOutButton,i),!this._disabled&&t._zoom!==t.getMinZoom()||mi(this._zoomOutButton,i),!this._disabled&&t._zoom!==t.getMaxZoom()||mi(this._zoomInButton,i)}});$i.mergeOptions({zoomControl:!0}),$i.addInitHook(function(){this.options.zoomControl&&(this.zoomControl=new ee,this.addControl(this.zoomControl))});var ne=te.extend({options:{position:"bottomleft",maxWidth:100,metric:!0,imperial:!0},onAdd:function(t){var i="leaflet-control-scale",e=ui("div",i),n=this.options;return this._addScales(n,i+"-line",e),t.on(n.updateWhenIdle?"moveend":"move",this._update,this),t.whenReady(this._update,this),e},onRemove:function(t){t.off(this.options.updateWhenIdle?"moveend":"move",this._update,this)},_addScales:function(t,i,e){t.metric&&(this._mScale=ui("div",i,e)),t.imperial&&(this._iScale=ui("div",i,e))},_update:function(){var t=this._map,i=t.getSize().y/2,e=t.distance(t.containerPointToLatLng([0,i]),t.containerPointToLatLng([this.options.maxWidth,i]));this._updateScales(e)},_updateScales:function(t){this.options.metric&&t&&this._updateMetric(t),this.options.imperial&&t&&this._updateImperial(t)},_updateMetric:function(t){var i=this._getRoundNum(t),e=i<1e3?i+" m":i/1e3+" km";this._updateScale(this._mScale,e,i/t)},_updateImperial:function(t){var i,e,n,o=3.2808399*t;5280Leaflet'},initialize:function(t){p(this,t),this._attributions={}},onAdd:function(t){for(var i in(t.attributionControl=this)._container=ui("div","leaflet-control-attribution"),Di(this._container),t._layers)t._layers[i].getAttribution&&this.addAttribution(t._layers[i].getAttribution());return this._update(),this._container},setPrefix:function(t){return this.options.prefix=t,this._update(),this},addAttribution:function(t){return t&&(this._attributions[t]||(this._attributions[t]=0),this._attributions[t]++,this._update()),this},removeAttribution:function(t){return t&&this._attributions[t]&&(this._attributions[t]--,this._update()),this},_update:function(){if(this._map){var t=[];for(var i in this._attributions)this._attributions[i]&&t.push(i);var e=[];this.options.prefix&&e.push(this.options.prefix),t.length&&e.push(t.join(", ")),this._container.innerHTML=e.join(" | ")}}});$i.mergeOptions({attributionControl:!0}),$i.addInitHook(function(){this.options.attributionControl&&(new oe).addTo(this)});te.Layers=ie,te.Zoom=ee,te.Scale=ne,te.Attribution=oe,Qi.layers=function(t,i,e){return new ie(t,i,e)},Qi.zoom=function(t){return new ee(t)},Qi.scale=function(t){return new ne(t)},Qi.attribution=function(t){return new oe(t)};var se=E.extend({initialize:function(t){this._map=t},enable:function(){return this._enabled||(this._enabled=!0,this.addHooks()),this},disable:function(){return this._enabled&&(this._enabled=!1,this.removeHooks()),this},enabled:function(){return!!this._enabled}});se.addTo=function(t,i){return t.addHandler(i,this),this};var re,ae={Events:Z},he=Tt?"touchstart mousedown":"mousedown",ue={mousedown:"mouseup",touchstart:"touchend",pointerdown:"touchend",MSPointerDown:"touchend"},le={mousedown:"mousemove",touchstart:"touchmove",pointerdown:"touchmove",MSPointerDown:"touchmove"},ce=k.extend({options:{clickTolerance:3},initialize:function(t,i,e,n){p(this,n),this._element=t,this._dragStartTarget=i||t,this._preventOutline=e},enable:function(){this._enabled||(ki(this._dragStartTarget,he,this._onDown,this),this._enabled=!0)},disable:function(){this._enabled&&(ce._dragging===this&&this.finishDrag(),Ai(this._dragStartTarget,he,this._onDown,this),this._enabled=!1,this._moved=!1)},_onDown:function(t){if(!t._simulated&&this._enabled&&(this._moved=!1,!pi(this._element,"leaflet-zoom-anim")&&!(ce._dragging||t.shiftKey||1!==t.which&&1!==t.button&&!t.touches||((ce._dragging=this)._preventOutline&&Mi(this._element),Ti(),Qt(),this._moving)))){this.fire("down");var i=t.touches?t.touches[0]:t,e=Si(this._element);this._startPoint=new B(i.clientX,i.clientY),this._parentScale=Ei(e),ki(document,le[t.type],this._onMove,this),ki(document,ue[t.type],this._onUp,this)}},_onMove:function(t){if(!t._simulated&&this._enabled)if(t.touches&&1i.max.x&&(e|=2),t.yi.max.y&&(e|=8),e}function ge(t,i,e,n){var o,s=i.x,r=i.y,a=e.x-s,h=e.y-r,u=a*a+h*h;return 0this._layersMaxZoom&&this.setZoom(this._layersMaxZoom),void 0===this.options.minZoom&&this._layersMinZoom&&this.getZoom()t.y!=n.y>t.y&&t.x<(n.x-e.x)*(t.y-e.y)/(n.y-e.y)+e.x&&(u=!u);return u||je.prototype._containsPoint.call(this,t,!0)}});var He=ke.extend({initialize:function(t,i){p(this,i),this._layers={},t&&this.addData(t)},addData:function(t){var i,e,n,o=v(t)?t:t.features;if(o){for(i=0,e=o.length;iu.x&&(l=s.x+n-u.x+h.x),s.x-l-a.x<0&&(l=s.x-a.x),s.y+e+h.y>u.y&&(c=s.y+e-u.y+h.y),s.y-c-a.y<0&&(c=s.y-a.y),(l||c)&&t.fire("autopanstart").panBy([l,c])}},_onCloseButtonClick:function(t){this._close(),Wi(t)},_getAnchor:function(){return I(this._source&&this._source._getPopupAnchor?this._source._getPopupAnchor():[0,0])}});$i.mergeOptions({closePopupOnClick:!0}),$i.include({openPopup:function(t,i,e){return t instanceof sn||(t=new sn(e).setContent(t)),i&&t.setLatLng(i),this.hasLayer(t)?this:(this._popup&&this._popup.options.autoClose&&this.closePopup(),this._popup=t,this.addLayer(t))},closePopup:function(t){return t&&t!==this._popup||(t=this._popup,this._popup=null),t&&this.removeLayer(t),this}}),Ee.include({bindPopup:function(t,i){return t instanceof sn?(p(t,i),(this._popup=t)._source=this):(this._popup&&!i||(this._popup=new sn(i,this)),this._popup.setContent(t)),this._popupHandlersAdded||(this.on({click:this._openPopup,keypress:this._onKeyPress,remove:this.closePopup,move:this._movePopup}),this._popupHandlersAdded=!0),this},unbindPopup:function(){return this._popup&&(this.off({click:this._openPopup,keypress:this._onKeyPress,remove:this.closePopup,move:this._movePopup}),this._popupHandlersAdded=!1,this._popup=null),this},openPopup:function(t,i){return this._popup&&this._map&&(i=this._popup._prepareOpen(this,t,i),this._map.openPopup(this._popup,i)),this},closePopup:function(){return this._popup&&this._popup._close(),this},togglePopup:function(t){return this._popup&&(this._popup._map?this.closePopup():this.openPopup(t)),this},isPopupOpen:function(){return!!this._popup&&this._popup.isOpen()},setPopupContent:function(t){return this._popup&&this._popup.setContent(t),this},getPopup:function(){return this._popup},_openPopup:function(t){var i=t.layer||t.target;this._popup&&this._map&&(Wi(t),i instanceof Re?this.openPopup(t.layer||t.target,t.latlng):this._map.hasLayer(this._popup)&&this._popup._source===i?this.closePopup():this.openPopup(i,t.latlng))},_movePopup:function(t){this._popup.setLatLng(t.latlng)},_onKeyPress:function(t){13===t.originalEvent.keyCode&&this._openPopup(t)}});var rn=on.extend({options:{pane:"tooltipPane",offset:[0,0],direction:"auto",permanent:!1,sticky:!1,interactive:!1,opacity:.9},onAdd:function(t){on.prototype.onAdd.call(this,t),this.setOpacity(this.options.opacity),t.fire("tooltipopen",{tooltip:this}),this._source&&this._source.fire("tooltipopen",{tooltip:this},!0)},onRemove:function(t){on.prototype.onRemove.call(this,t),t.fire("tooltipclose",{tooltip:this}),this._source&&this._source.fire("tooltipclose",{tooltip:this},!0)},getEvents:function(){var t=on.prototype.getEvents.call(this);return Tt&&!this.options.permanent&&(t.preclick=this._close),t},_close:function(){this._map&&this._map.closeTooltip(this)},_initLayout:function(){var t="leaflet-tooltip "+(this.options.className||"")+" leaflet-zoom-"+(this._zoomAnimated?"animated":"hide");this._contentNode=this._container=ui("div",t)},_updateLayout:function(){},_adjustPan:function(){},_setPosition:function(t){var i=this._map,e=this._container,n=i.latLngToContainerPoint(i.getCenter()),o=i.layerPointToContainerPoint(t),s=this.options.direction,r=e.offsetWidth,a=e.offsetHeight,h=I(this.options.offset),u=this._getAnchor();t="top"===s?t.add(I(-r/2+h.x,-a+h.y+u.y,!0)):"bottom"===s?t.subtract(I(r/2-h.x,-h.y,!0)):"center"===s?t.subtract(I(r/2+h.x,a/2-u.y+h.y,!0)):"right"===s||"auto"===s&&o.xthis.options.maxZoom||ethis.options.maxZoom||void 0!==this.options.minZoom&&oe.max.x)||!i.wrapLat&&(t.ye.max.y))return!1}if(!this.options.bounds)return!0;var n=this._tileCoordsToBounds(t);return D(this.options.bounds).overlaps(n)},_keyToBounds:function(t){return this._tileCoordsToBounds(this._keyToTileCoords(t))},_tileCoordsToNwSe:function(t){var i=this._map,e=this.getTileSize(),n=t.scaleBy(e),o=n.add(e);return[i.unproject(n,t.z),i.unproject(o,t.z)]},_tileCoordsToBounds:function(t){var i=this._tileCoordsToNwSe(t),e=new N(i[0],i[1]);return this.options.noWrap||(e=this._map.wrapLatLngBounds(e)),e},_tileCoordsToKey:function(t){return t.x+":"+t.y+":"+t.z},_keyToTileCoords:function(t){var i=t.split(":"),e=new B(+i[0],+i[1]);return e.z=+i[2],e},_removeTile:function(t){var i=this._tiles[t];i&&(li(i.el),delete this._tiles[t],this.fire("tileunload",{tile:i.el,coords:this._keyToTileCoords(t)}))},_initTile:function(t){mi(t,"leaflet-tile");var i=this.getTileSize();t.style.width=i.x+"px",t.style.height=i.y+"px",t.onselectstart=l,t.onmousemove=l,et&&this.options.opacity<1&&yi(t,this.options.opacity),st&&!rt&&(t.style.WebkitBackfaceVisibility="hidden")},_addTile:function(t,i){var e=this._getTilePos(t),n=this._tileCoordsToKey(t),o=this.createTile(this._wrapCoords(t),a(this._tileReady,this,t));this._initTile(o),this.createTile.length<2&&M(a(this._tileReady,this,t,null,o)),Pi(o,e),this._tiles[n]={el:o,coords:t,current:!0},i.appendChild(o),this.fire("tileloadstart",{tile:o,coords:t})},_tileReady:function(t,i,e){i&&this.fire("tileerror",{error:i,tile:e,coords:t});var n=this._tileCoordsToKey(t);(e=this._tiles[n])&&(e.loaded=+new Date,this._map._fadeAnimated?(yi(e.el,0),C(this._fadeFrame),this._fadeFrame=M(this._updateOpacity,this)):(e.active=!0,this._pruneTiles()),i||(mi(e.el,"leaflet-tile-loaded"),this.fire("tileload",{tile:e.el,coords:t})),this._noTilesToLoad()&&(this._loading=!1,this.fire("load"),et||!this._map._fadeAnimated?M(this._pruneTiles,this):setTimeout(a(this._pruneTiles,this),250)))},_getTilePos:function(t){return t.scaleBy(this.getTileSize()).subtract(this._level.origin)},_wrapCoords:function(t){var i=new B(this._wrapX?r(t.x,this._wrapX):t.x,this._wrapY?r(t.y,this._wrapY):t.y);return i.z=t.z,i},_pxBoundsToTileRange:function(t){var i=this.getTileSize();return new O(t.min.unscaleBy(i).floor(),t.max.unscaleBy(i).ceil().subtract([1,1]))},_noTilesToLoad:function(){for(var t in this._tiles)if(!this._tiles[t].loaded)return!1;return!0}});var un=hn.extend({options:{minZoom:0,maxZoom:18,subdomains:"abc",errorTileUrl:"",zoomOffset:0,tms:!1,zoomReverse:!1,detectRetina:!1,crossOrigin:!1},initialize:function(t,i){this._url=t,(i=p(this,i)).detectRetina&&Ct&&0')}}catch(t){return function(t){return document.createElement("<"+t+' xmlns="urn:schemas-microsoft.com:vml" class="lvml">')}}}(),fn={_initContainer:function(){this._container=ui("div","leaflet-vml-container")},_update:function(){this._map._animatingZoom||(_n.prototype._update.call(this),this.fire("update"))},_initPath:function(t){var i=t._container=mn("shape");mi(i,"leaflet-vml-shape "+(this.options.className||"")),i.coordsize="1 1",t._path=mn("path"),i.appendChild(t._path),this._updateStyle(t),this._layers[u(t)]=t},_addPath:function(t){var i=t._container;this._container.appendChild(i),t.options.interactive&&t.addInteractiveTarget(i)},_removePath:function(t){var i=t._container;li(i),t.removeInteractiveTarget(i),delete this._layers[u(t)]},_updateStyle:function(t){var i=t._stroke,e=t._fill,n=t.options,o=t._container;o.stroked=!!n.stroke,o.filled=!!n.fill,n.stroke?(i||(i=t._stroke=mn("stroke")),o.appendChild(i),i.weight=n.weight+"px",i.color=n.color,i.opacity=n.opacity,n.dashArray?i.dashStyle=v(n.dashArray)?n.dashArray.join(" "):n.dashArray.replace(/( *, *)/g," "):i.dashStyle="",i.endcap=n.lineCap.replace("butt","flat"),i.joinstyle=n.lineJoin):i&&(o.removeChild(i),t._stroke=null),n.fill?(e||(e=t._fill=mn("fill")),o.appendChild(e),e.color=n.fillColor||n.color,e.opacity=n.fillOpacity):e&&(o.removeChild(e),t._fill=null)},_updateCircle:function(t){var i=t._point.round(),e=Math.round(t._radius),n=Math.round(t._radiusY||e);this._setPath(t,t._empty()?"M0 0":"AL "+i.x+","+i.y+" "+e+","+n+" 0,23592600")},_setPath:function(t,i){t._path.v=i},_bringToFront:function(t){_i(t._container)},_bringToBack:function(t){di(t._container)}},gn=kt?mn:$,vn=_n.extend({getEvents:function(){var t=_n.prototype.getEvents.call(this);return t.zoomstart=this._onZoomStart,t},_initContainer:function(){this._container=gn("svg"),this._container.setAttribute("pointer-events","none"),this._rootGroup=gn("g"),this._container.appendChild(this._rootGroup)},_destroyContainer:function(){li(this._container),Ai(this._container),delete this._container,delete this._rootGroup,delete this._svgSize},_onZoomStart:function(){this._update()},_update:function(){if(!this._map._animatingZoom||!this._bounds){_n.prototype._update.call(this);var t=this._bounds,i=t.getSize(),e=this._container;this._svgSize&&this._svgSize.equals(i)||(this._svgSize=i,e.setAttribute("width",i.x),e.setAttribute("height",i.y)),Pi(e,t.min),e.setAttribute("viewBox",[t.min.x,t.min.y,i.x,i.y].join(" ")),this.fire("update")}},_initPath:function(t){var i=t._path=gn("path");t.options.className&&mi(i,t.options.className),t.options.interactive&&mi(i,"leaflet-interactive"),this._updateStyle(t),this._layers[u(t)]=t},_addPath:function(t){this._rootGroup||this._initContainer(),this._rootGroup.appendChild(t._path),t.addInteractiveTarget(t._path)},_removePath:function(t){li(t._path),t.removeInteractiveTarget(t._path),delete this._layers[u(t)]},_updatePath:function(t){t._project(),t._update()},_updateStyle:function(t){var i=t._path,e=t.options;i&&(e.stroke?(i.setAttribute("stroke",e.color),i.setAttribute("stroke-opacity",e.opacity),i.setAttribute("stroke-width",e.weight),i.setAttribute("stroke-linecap",e.lineCap),i.setAttribute("stroke-linejoin",e.lineJoin),e.dashArray?i.setAttribute("stroke-dasharray",e.dashArray):i.removeAttribute("stroke-dasharray"),e.dashOffset?i.setAttribute("stroke-dashoffset",e.dashOffset):i.removeAttribute("stroke-dashoffset")):i.setAttribute("stroke","none"),e.fill?(i.setAttribute("fill",e.fillColor||e.color),i.setAttribute("fill-opacity",e.fillOpacity),i.setAttribute("fill-rule",e.fillRule||"evenodd")):i.setAttribute("fill","none"))},_updatePoly:function(t,i){this._setPath(t,Q(t._parts,i))},_updateCircle:function(t){var i=t._point,e=Math.max(Math.round(t._radius),1),n="a"+e+","+(Math.max(Math.round(t._radiusY),1)||e)+" 0 1,0 ",o=t._empty()?"M0 0":"M"+(i.x-e)+","+i.y+n+2*e+",0 "+n+2*-e+",0 ";this._setPath(t,o)},_setPath:function(t,i){t._path.setAttribute("d",i)},_bringToFront:function(t){_i(t._path)},_bringToBack:function(t){di(t._path)}});function yn(t){return Zt||kt?new vn(t):null}kt&&vn.include(fn),$i.include({getRenderer:function(t){var i=t.options.renderer||this._getPaneRenderer(t.options.pane)||this.options.renderer||this._renderer;return i||(i=this._renderer=this._createRenderer()),this.hasLayer(i)||this.addLayer(i),i},_getPaneRenderer:function(t){if("overlayPane"===t||void 0===t)return!1;var i=this._paneRenderers[t];return void 0===i&&(i=this._createRenderer({pane:t}),this._paneRenderers[t]=i),i},_createRenderer:function(t){return this.options.preferCanvas&&pn(t)||yn(t)}});var xn=We.extend({initialize:function(t,i){We.prototype.initialize.call(this,this._boundsToLatLngs(t),i)},setBounds:function(t){return this.setLatLngs(this._boundsToLatLngs(t))},_boundsToLatLngs:function(t){return[(t=D(t)).getSouthWest(),t.getNorthWest(),t.getNorthEast(),t.getSouthEast()]}});vn.create=gn,vn.pointsToPath=Q,He.geometryToLayer=Fe,He.coordsToLatLng=Ve,He.coordsToLatLngs=qe,He.latLngToCoords=Ge,He.latLngsToCoords=Ke,He.getFeature=Ye,He.asFeature=Xe,$i.mergeOptions({boxZoom:!0});var wn=se.extend({initialize:function(t){this._map=t,this._container=t._container,this._pane=t._panes.overlayPane,this._resetStateTimeout=0,t.on("unload",this._destroy,this)},addHooks:function(){ki(this._container,"mousedown",this._onMouseDown,this)},removeHooks:function(){Ai(this._container,"mousedown",this._onMouseDown,this)},moved:function(){return this._moved},_destroy:function(){li(this._pane),delete this._pane},_resetState:function(){this._resetStateTimeout=0,this._moved=!1},_clearDeferredResetState:function(){0!==this._resetStateTimeout&&(clearTimeout(this._resetStateTimeout),this._resetStateTimeout=0)},_onMouseDown:function(t){if(!t.shiftKey||1!==t.which&&1!==t.button)return!1;this._clearDeferredResetState(),this._resetState(),Qt(),Ti(),this._startPoint=this._map.mouseEventToContainerPoint(t),ki(document,{contextmenu:Wi,mousemove:this._onMouseMove,mouseup:this._onMouseUp,keydown:this._onKeyDown},this)},_onMouseMove:function(t){this._moved||(this._moved=!0,this._box=ui("div","leaflet-zoom-box",this._container),mi(this._container,"leaflet-crosshair"),this._map.fire("boxzoomstart")),this._point=this._map.mouseEventToContainerPoint(t);var i=new O(this._point,this._startPoint),e=i.getSize();Pi(this._box,i.min),this._box.style.width=e.x+"px",this._box.style.height=e.y+"px"},_finish:function(){this._moved&&(li(this._box),fi(this._container,"leaflet-crosshair")),ti(),zi(),Ai(document,{contextmenu:Wi,mousemove:this._onMouseMove,mouseup:this._onMouseUp,keydown:this._onKeyDown},this)},_onMouseUp:function(t){if((1===t.which||1===t.button)&&(this._finish(),this._moved)){this._clearDeferredResetState(),this._resetStateTimeout=setTimeout(a(this._resetState,this),0);var i=new N(this._map.containerPointToLatLng(this._startPoint),this._map.containerPointToLatLng(this._point));this._map.fitBounds(i).fire("boxzoomend",{boxZoomBounds:i})}},_onKeyDown:function(t){27===t.keyCode&&this._finish()}});$i.addInitHook("addHandler","boxZoom",wn),$i.mergeOptions({doubleClickZoom:!0});var Pn=se.extend({addHooks:function(){this._map.on("dblclick",this._onDoubleClick,this)},removeHooks:function(){this._map.off("dblclick",this._onDoubleClick,this)},_onDoubleClick:function(t){var i=this._map,e=i.getZoom(),n=i.options.zoomDelta,o=t.originalEvent.shiftKey?e-n:e+n;"center"===i.options.doubleClickZoom?i.setZoom(o):i.setZoomAround(t.containerPoint,o)}});$i.addInitHook("addHandler","doubleClickZoom",Pn),$i.mergeOptions({dragging:!0,inertia:!rt,inertiaDeceleration:3400,inertiaMaxSpeed:1/0,easeLinearity:.2,worldCopyJump:!1,maxBoundsViscosity:0});var Ln=se.extend({addHooks:function(){if(!this._draggable){var t=this._map;this._draggable=new ce(t._mapPane,t._container),this._draggable.on({dragstart:this._onDragStart,drag:this._onDrag,dragend:this._onDragEnd},this),this._draggable.on("predrag",this._onPreDragLimit,this),t.options.worldCopyJump&&(this._draggable.on("predrag",this._onPreDragWrap,this),t.on("zoomend",this._onZoomEnd,this),t.whenReady(this._onZoomEnd,this))}mi(this._map._container,"leaflet-grab leaflet-touch-drag"),this._draggable.enable(),this._positions=[],this._times=[]},removeHooks:function(){fi(this._map._container,"leaflet-grab"),fi(this._map._container,"leaflet-touch-drag"),this._draggable.disable()},moved:function(){return this._draggable&&this._draggable._moved},moving:function(){return this._draggable&&this._draggable._moving},_onDragStart:function(){var t=this._map;if(t._stop(),this._map.options.maxBounds&&this._map.options.maxBoundsViscosity){var i=D(this._map.options.maxBounds);this._offsetLimit=R(this._map.latLngToContainerPoint(i.getNorthWest()).multiplyBy(-1),this._map.latLngToContainerPoint(i.getSouthEast()).multiplyBy(-1).add(this._map.getSize())),this._viscosity=Math.min(1,Math.max(0,this._map.options.maxBoundsViscosity))}else this._offsetLimit=null;t.fire("movestart").fire("dragstart"),t.options.inertia&&(this._positions=[],this._times=[])},_onDrag:function(t){if(this._map.options.inertia){var i=this._lastTime=+new Date,e=this._lastPos=this._draggable._absPos||this._draggable._newPos;this._positions.push(e),this._times.push(i),this._prunePositions(i)}this._map.fire("move",t).fire("drag",t)},_prunePositions:function(t){for(;1i.max.x&&(t.x=this._viscousLimit(t.x,i.max.x)),t.y>i.max.y&&(t.y=this._viscousLimit(t.y,i.max.y)),this._draggable._newPos=this._draggable._startPos.add(t)}},_onPreDragWrap:function(){var t=this._worldWidth,i=Math.round(t/2),e=this._initialWorldOffset,n=this._draggable._newPos.x,o=(n-i+e)%t+i-e,s=(n+i+e)%t-i-e,r=Math.abs(o+e)i.getMaxZoom()&&1 + @@ -206,6 +207,7 @@ + From 22f2d37f1fb0b9f00e9aaab9d5ebfbb31db45049 Mon Sep 17 00:00:00 2001 From: Moe Date: Wed, 29 Jul 2020 16:38:04 -0700 Subject: [PATCH 048/175] Show GPS data on Video Recordings (if they have it) --- libs/webServerPaths.js | 6 +++- web/libs/js/dash2.elements.js | 34 +++++++++++++++--- web/libs/js/dash2.gps.js | 66 ++++++++++++++++++++++++++++++++++ web/pages/blocks/videoview.ejs | 12 ++++++- web/pages/home.ejs | 1 + 5 files changed, 112 insertions(+), 7 deletions(-) create mode 100644 web/libs/js/dash2.gps.js diff --git a/libs/webServerPaths.js b/libs/webServerPaths.js index d7b0dac8..b17d3498 100644 --- a/libs/webServerPaths.js +++ b/libs/webServerPaths.js @@ -1558,7 +1558,11 @@ module.exports = function(s,config,lang,app,io){ req.dir=s.getVideoDirectory(r[0])+req.params.file fs.stat(req.dir,function(err,stats){ if (!err){ - s.streamMp4FileOverHttp(req.dir,req,res) + if(req.query.json === 'true'){ + s.closeJsonResponse(res,r[0]) + }else{ + s.streamMp4FileOverHttp(req.dir,req,res) + } }else{ res.end(user.lang['File Not Found in Filesystem']) } diff --git a/web/libs/js/dash2.elements.js b/web/libs/js/dash2.elements.js index 692339bb..38e2cd49 100644 --- a/web/libs/js/dash2.elements.js +++ b/web/libs/js/dash2.elements.js @@ -157,12 +157,12 @@ $(document).ready(function(e){ e.preventDefault(); e.href=$(this).attr('href') var el = $('#video_viewer') - var modalBody = el.find('.modal-body') + var videoContainer = el.find('.video-container') el.find('.modal-title span').html(e.mon.name+' - '+e.file) var html = '
' - modalBody.html(html) + videoContainer.html(html) el.find('video')[0].onerror = function(){ - modalBody.find('.msg').text(lang.h265BrowserText1) + videoContainer.find('.msg').text(lang.h265BrowserText1) } el.attr('mid',e.mid); footer = el.find('.modal-footer'); @@ -178,6 +178,28 @@ $(document).ready(function(e){ if(d.ok !== true)console.log(d,new Error()) }) } + setTimeout(function(){ + destroyGpsHandlerForVideoFile(`video_viewer_gps_map_map`) + var videoElement = videoContainer.find('.video_video') + var gpsContainer = videoContainer.next() + var fullWidth = 'col-md-12' + var partialWidth = 'col-md-8' + createGpsHandlerForVideoFile({ + ke: e.ke, + mid: e.mid, + file: e.file, + targetVideoElement: videoElement, + targetMapElement: `video_viewer_gps_map`, + },function(response){ + if(response.ok){ + videoContainer.addClass(partialWidth).removeClass(fullWidth) + gpsContainer.show() + }else{ + videoContainer.addClass(fullWidth).removeClass(partialWidth) + gpsContainer.hide() + } + }) + },2000) break; case'delete': e.preventDefault(); @@ -766,8 +788,10 @@ $(document).ready(function(e){ }) $('.modal').on('hidden.bs.modal',function(){ - $(this).find('video').remove(); - $(this).find('iframe').attr('src','about:blank'); + var el = $(this) + el.find('video').remove(); + el.find('iframe').attr('src','about:blank'); + if(el.attr('id') === 'video_viewer')destroyGpsHandlerForVideoFile(`video_viewer_gps_map_map`) }); $('.modal').on('shown.bs.modal',function(){ e={e:$(this).find('.flex-container-modal-body')} diff --git a/web/libs/js/dash2.gps.js b/web/libs/js/dash2.gps.js new file mode 100644 index 00000000..13ef369c --- /dev/null +++ b/web/libs/js/dash2.gps.js @@ -0,0 +1,66 @@ +$(document).ready(function(){ + var createMapElement = function(options){ + $(`#${options.id}`).html(`
`) + var vidViewMap = L.map(options.id + '_map').setView(options.initalView, options.zoom) + var mapBoxMarker; + L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', { + attribution: 'OpenStreet Map' + }).addTo(vidViewMap) + + if(options.marker)mapBoxMarker = L.marker(options.marker).addTo(vidViewMap) + return { + map: vidViewMap, + marker: mapBoxMarker, + } + } + window.destroyGpsHandlerForVideoFile = function(mapId){ + var vidViewMap = $(`#${mapId}`) + if (vidViewMap.length > 0) { + try{ + vidViewMap.off(); + vidViewMap.remove(); + }catch(err){ + console.log(err) + } + } + } + window.createGpsHandlerForVideoFile = function(options,callback){ + var groupKey = options.ke + var monitorId = options.mid + var filename = options.file + var videoElement = options.targetVideoElement + $.get(getApiPrefix() + '/videos/' + groupKey + '/' + monitorId + '/' + filename + '?json=true',function(video){ + var response = {ok: false} + var gps = video.details.gps + console.log(video) + if(gps && gps[0]){ + var gpsPoints = {} + var firstMarker = gps[0] + + var videoStartTime = new Date(video.time) + $.each(gps,function(n,point){ + var pointTime = new Date(point.time) + var seekPosition = (pointTime - videoStartTime) / 1000 + gpsPoints[pointTime] = point + }) + response.ok = true + response.gpsPoints = gpsPoints + callback(response) + response.elements = createMapElement({ + id: options.targetMapElement, + initalView: [firstMarker.lat,firstMarker.lng], + marker: [firstMarker.lat,firstMarker.lng], + zoom: 5, + }) + videoElement.on('timeupdate',function(){ + var point = gpsPoints[parseInt(this.currentTime)] + if(point){ + mapBoxMarker.setLatLng([point.lat, point.lng]).update() + } + }) + }else{ + callback(response) + } + }) + } +}) diff --git a/web/pages/blocks/videoview.ejs b/web/pages/blocks/videoview.ejs index 65db05a7..86b768d9 100644 --- a/web/pages/blocks/videoview.ejs +++ b/web/pages/blocks/videoview.ejs @@ -66,7 +66,17 @@
- +