1 | process.on('uncaughtException', function (err) {
|
2 | console.error('uncaughtException',err);
|
3 | });
|
4 | var fs = require('fs');
|
5 | var path = require('path');
|
6 | var mysql = require('mysql');
|
7 | var moment = require('moment');
|
8 | var exec = require('child_process').exec;
|
9 | var spawn = require('child_process').spawn;
|
10 | var config=require('./conf.json');
|
11 | var sql=mysql.createConnection(config.db);
|
12 |
|
13 |
|
14 | s={lock:{}};
|
15 | if(config.cron===undefined)config.cron={};
|
16 | if(config.cron.deleteOld===undefined)config.cron.deleteOld=true;
|
17 | if(config.cron.deleteOrphans===undefined)config.cron.deleteOrphans=false;
|
18 | if(config.cron.deleteNoVideo===undefined)config.cron.deleteNoVideo=true;
|
19 | if(config.cron.deleteOverMax===undefined)config.cron.deleteOverMax=true;
|
20 | if(config.cron.deleteLogs===undefined)config.cron.deleteLogs=true;
|
21 | if(config.cron.deleteEvents===undefined)config.cron.deleteEvents=true;
|
22 | if(config.cron.interval===undefined)config.cron.interval=1;
|
23 |
|
24 | if(!config.ip||config.ip===''||config.ip.indexOf('0.0.0.0')>-1)config.ip='localhost';
|
25 | if(!config.videosDir)config.videosDir=__dirname+'/videos/';
|
26 | if(!config.addStorage){config.addStorage=[]}
|
27 | s.checkCorrectPathEnding=function(x){
|
28 | var length=x.length
|
29 | if(x.charAt(length-1)!=='/'){
|
30 | x=x+'/'
|
31 | }
|
32 | return x.replace('__DIR__',__dirname)
|
33 | }
|
34 | s.dir={
|
35 | videos:s.checkCorrectPathEnding(config.videosDir),
|
36 | addStorage:config.addStorage,
|
37 | };
|
38 | s.moment=function(e,x){
|
39 | if(!e){e=new Date};if(!x){x='YYYY-MM-DDTHH-mm-ss'};
|
40 | return moment(e).format(x);
|
41 | }
|
42 | s.nameToTime=function(x){x=x.replace('.webm','').replace('.mp4','').split('T'),x[1]=x[1].replace(/-/g,':');x=x.join(' ');return x;}
|
43 | io = require('socket.io-client')('ws://'+config.ip+':'+config.port);
|
44 | s.cx=function(x){x.cronKey=config.cron.key;return io.emit('cron',x)}
|
45 |
|
46 | s.tx=function(x,y){s.cx({f:'s.tx',data:x,to:y})}
|
47 | s.video=function(x,y){s.cx({f:'s.video',data:x,file:y})}
|
48 |
|
49 | s.cx({f:'init',time:moment()})
|
50 | s.getVideoDirectory=function(e){
|
51 | if(e.mid&&!e.id){e.id=e.mid};
|
52 | if(e.details&&(e.details instanceof Object)===false){
|
53 | try{e.details=JSON.parse(e.details)}catch(err){}
|
54 | }
|
55 | if(e.details.dir&&e.details.dir!==''){
|
56 | return s.checkCorrectPathEnding(e.details.dir)+e.ke+'/'+e.id+'/'
|
57 | }else{
|
58 | return s.dir.videos+e.ke+'/'+e.id+'/';
|
59 | }
|
60 | }
|
61 | s.checkFilterRules=function(v){
|
62 | Object.keys(v.d.filters).forEach(function(m,b){
|
63 | b=v.d.filters[m];
|
64 | if(b.enabled==="1"){
|
65 | b.ar=[v.ke];
|
66 | b.sql=[];
|
67 | b.where.forEach(function(j,k){
|
68 | if(j.p1==='ke'){j.p3=v.ke}
|
69 | switch(j.p3_type){
|
70 | case'function':
|
71 | b.sql.push(j.p1+' '+j.p2+' '+j.p3)
|
72 | break;
|
73 | default:
|
74 | b.sql.push(j.p1+' '+j.p2+' ?')
|
75 | b.ar.push(j.p3)
|
76 | break;
|
77 | }
|
78 | })
|
79 | b.sql='WHERE ke=? AND status != 0 AND details NOT LIKE \'%"archived":"1"%\' AND ('+b.sql.join(' AND ')+')';
|
80 | if(b.sort_by&&b.sort_by!==''){
|
81 | b.sql+=' ORDER BY `'+b.sort_by+'` '+b.sort_by_direction
|
82 | }
|
83 | if(b.limit&&b.limit!==''){
|
84 | b.sql+=' LIMIT '+b.limit
|
85 | }
|
86 | sql.query('SELECT * FROM Videos '+b.sql,b.ar,function(err,r){
|
87 | if(r&&r[0]){
|
88 | b.cx={
|
89 | f:'filters',
|
90 | name:b.name,
|
91 | videos:r,
|
92 | time:moment(),
|
93 | ke:v.ke,
|
94 | id:b.id
|
95 | };
|
96 | if(b.archive==="1"){
|
97 | s.cx({f:'filters',ff:'archive',videos:r,time:moment(),ke:v.ke,id:b.id});
|
98 | }else{
|
99 | if(b.delete==="1"){
|
100 | s.cx({f:'filters',ff:'delete',videos:r,time:moment(),ke:v.ke,id:b.id});
|
101 | }
|
102 | }
|
103 | if(b.email==="1"){
|
104 | b.cx.ff='email';
|
105 | b.cx.delete=b.delete;
|
106 | b.cx.mail=v.mail;
|
107 | b.cx.execute=b.execute;
|
108 | b.cx.query=b.sql;
|
109 | s.cx(b.cx);
|
110 | }
|
111 | if(b.execute&&b.execute!==""){
|
112 | s.cx({f:'filters',ff:'execute',execute:b.execute,time:moment()});
|
113 | }
|
114 | }
|
115 | })
|
116 |
|
117 | }
|
118 | })
|
119 | }
|
120 | s.checkForOrphanedFiles=function(v){
|
121 | if(config.cron.deleteOrphans===true){
|
122 | e={};
|
123 | sql.query('SELECT * FROM Monitors WHERE ke=?',[v.ke],function(arr,b) {
|
124 | b.forEach(function(mon,m){
|
125 | mon.dir=s.
|
126 | fs.readdir(s.getVideoDirectory(mon), function(err, items) {
|
127 | e.query=[];
|
128 | e.filesFound=[mon.ke,mon.mid];
|
129 | if(items&&items.length>0){
|
130 | items.forEach(function(v,n){
|
131 | e.query.push('time=?')
|
132 | e.filesFound.push(s.nameToTime(v))
|
133 | })
|
134 | sql.query('SELECT * FROM Videos WHERE ke=? AND mid=? AND ('+e.query.join(' OR ')+')',e.filesFound,function(arr,r) {
|
135 | if(!r){r=[]};
|
136 | e.foundSQLrows=[];
|
137 | r.forEach(function(v,n){
|
138 | v.index=e.filesFound.indexOf(s.moment(v.time,'YYYY-MM-DD HH:mm:ss'));
|
139 | if(v.index>-1){
|
140 | delete(items[v.index-2]);
|
141 | }
|
142 | });
|
143 | items.forEach(function(v,n){
|
144 | if(v&&v!==null){
|
145 | exec('rm '+s.getVideoDirectory(mon)+v);
|
146 | }
|
147 | })
|
148 | })
|
149 | }
|
150 | })
|
151 | });
|
152 | });
|
153 | }
|
154 | }
|
155 | s.cron=function(){
|
156 | x={};
|
157 | s.cx({f:'start',time:moment()})
|
158 | sql.query('SELECT ke,uid,details,mail FROM Users WHERE details NOT LIKE \'%"sub"%\'', function(arr,r) {
|
159 | if(r&&r[0]){
|
160 | arr={};
|
161 | r.forEach(function(v){
|
162 | if(!arr[v.ke]){arr[v.ke]=0;}else{return false;}
|
163 |
|
164 | v.d=JSON.parse(v.details);
|
165 |
|
166 | if(!v.d.size||v.d.size==''){v.d.size=10000}else{v.d.size=parseFloat(v.d.size)};
|
167 |
|
168 | if(!v.d.days||v.d.days==''){v.d.days=5}else{v.d.days=parseFloat(v.d.days)};
|
169 |
|
170 | if(!v.d.log_days||v.d.log_days==''){v.d.log_days=10}else{v.d.log_days=parseFloat(v.d.log_days)};
|
171 | if(config.cron.deleteLogs===true&&v.d.log_days!==0){
|
172 | sql.query("DELETE FROM Logs WHERE ke=? AND `time` < DATE_SUB(NOW(), INTERVAL ? DAY)",[v.ke,v.d.log_days],function(err,rrr){
|
173 | if(err)return console.log(err);
|
174 | s.cx({f:'deleteLogs',msg:rrr.affectedRows+' SQL rows older than '+v.d.log_days+' days deleted',ke:v.ke,time:moment()})
|
175 | })
|
176 | }
|
177 |
|
178 | if(!v.d.event_days||v.d.event_days==''){v.d.event_days=10}else{v.d.event_days=parseFloat(v.d.event_days)};
|
179 | if(config.cron.deleteEvents===true&&v.d.event_days!==0){
|
180 | sql.query("DELETE FROM Events WHERE ke=? AND `time` < DATE_SUB(NOW(), INTERVAL ? DAY)",[v.ke,v.d.event_days],function(err,rrr){
|
181 | if(err)return console.log(err);
|
182 | s.cx({f:'deleteEvents',msg:rrr.affectedRows+' SQL rows older than '+v.d.event_days+' days deleted',ke:v.ke,time:moment()})
|
183 | })
|
184 | }
|
185 |
|
186 | if(!v.d.filters||v.d.filters==''){
|
187 | v.d.filters={};
|
188 | }
|
189 |
|
190 | if(config.cron.deleteOld===true){
|
191 | v.d.filters.deleteOldByCron={
|
192 | "id":"deleteOldByCron",
|
193 | "name":"deleteOldByCron",
|
194 | "sort_by":"time",
|
195 | "sort_by_direction":"ASC",
|
196 | "limit":"",
|
197 | "enabled":"1",
|
198 | "archive":"0",
|
199 | "email":"0",
|
200 | "delete":"1",
|
201 | "execute":"",
|
202 | "where":[{
|
203 | "p1":"end",
|
204 | "p2":"<",
|
205 | "p3":"NOW() - INTERVAL "+(v.d.days*24)+" HOUR",
|
206 | "p3_type":"function",
|
207 | }]
|
208 | };
|
209 | }
|
210 | s.checkFilterRules(v);
|
211 |
|
212 | v.fn=function(){
|
213 | if(s.lock[v.ke]!==1){
|
214 | s.lock[v.ke]=1;
|
215 | es={};
|
216 | sql.query('SELECT * FROM Videos WHERE ke = ? AND status != 0 AND details NOT LIKE \'%"archived":"1"%\' AND time < (NOW() - INTERVAL 10 MINUTE)',[v.ke],function(err,evs){
|
217 | if(evs&&evs[0]){
|
218 | es.del=[];es.ar=[v.ke];
|
219 | evs.forEach(function(ev){
|
220 | ev.dir=s.getVideoDirectory(ev)+s.moment(ev.time)+'.'+ev.ext;
|
221 | if(config.cron.deleteNoVideo===true&&fs.existsSync(ev.dir)!==true){
|
222 | s.video('delete',ev)
|
223 | es.del.push('(mid=? AND time=?)');
|
224 | es.ar.push(ev.mid),es.ar.push(ev.time);
|
225 | s.tx({f:'video_delete',filename:s.moment(ev.time)+'.'+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);
|
226 | }
|
227 | });
|
228 | if(config.cron.deleteNoVideo===true){
|
229 | s.cx({f:'deleteNoVideo',msg:es.del.length+' SQL rows with no file deleted',ke:v.ke,time:moment()})
|
230 | }
|
231 | }
|
232 |
|
233 | s.lock[v.ke]=0;
|
234 | setTimeout(function(){
|
235 | s.checkForOrphanedFiles(v);
|
236 | },3000)
|
237 | })
|
238 | }
|
239 | };
|
240 | v.fn();
|
241 | })
|
242 | }
|
243 | })
|
244 | s.timeout=setTimeout(function(){
|
245 | s.cron();
|
246 | },parseFloat(config.cron.interval)*60000*60)
|
247 | }
|
248 | s.cron();
|
249 |
|
250 | io.on('f',function(d){
|
251 | switch(d.f){
|
252 | case'start':case'restart':
|
253 | clearTimeout(s.timeout);
|
254 | s.cron();
|
255 | break;
|
256 | case'stop':
|
257 | clearTimeout(s.timeout);
|
258 | break;
|
259 | }
|
260 | })
|
261 |
|
262 |
|
263 | console.log('Shinobi : cron.js started') |
\ | No newline at end of file |