"use strict"; var cmn=require("../$common.js"), persist=require("node-persist"), crypto=require("crypto"), http=require("http"), https=require("https"), URL=require("url"); var moddir=null; persist=persist.create({ dir:"persist/changes", continuous:false, interval:false }); persist.initSync(); //urls: map(url => URLobject) //url: String //URLobject: {url, timeline: [[Date, hash, contents]]} var urls=persist.getItemSync("urls"); if(!urls){ urls={}; persist.setItemSync("urls",urls); } function URLobject(url){ if(!(this instanceof URLobject))return new URLobject(url); this.url=url; this.timeline=[]; } function fetch(method,url,data/*?*/,cb){ var cbcalled=false; if(!cb){ cb=data; data=undefined; if(!cb)throw new Error("No callback passed to fetch"); } try { url=URL.parse(url); } catch(e){ cb(-1,null); return; } var httpclass; switch(url.protocol){ case "http:": httpclass=http; break; case "https:": httpclass=https; break; default: cb(-1,null); return; } url.method=method; var req=httpclass.request(url,function(res){ var body=""; res.on("data",function(data){ body+=data; }); res.on("end",function(){ if(!cbcalled)cb(res.statusCode,body); cbcalled=true; }); res.on("error",function(err){ if(!cbcalled)cb(-1,err); cbcalled=true; }); }); req.on("error",function(err){ if(!cbcalled)cb(-1,err); cbcalled=true; }); if(data)req.write(data); req.end(); } var refresh_persist_timeout=null; function refreshURLs(){ var hashes={}; var i; var url; for(url in urls){ console.log("Fetching <"+url+">"); fetch("GET",url,function(url,status,body){ console.log("Got <"+url+">; status = "+status); if(status==-1){ hashes[url]=[new Date(),null,null]; } else { var hash=crypto.createHash("sha256"); hash.update(body); hashes[url]=[new Date(),hash.digest("hex"),body]; } if(!urls[url]){ console.log("WARNING: url <"+url+"> from hashes not found in urls!"); return; } //var last=urls[url].timeline[urls[url].timeline.length-1]; //if(last==undefined||hashes[url][1]==null||hashes[url][1]!=last[1]){ urls[url].timeline.push(hashes[url]); //} if(refresh_persist_timeout!=null)clearTimeout(refresh_persist_timeout); refresh_persist_timeout=setTimeout(function(){ persist.setItemSync("urls",urls); console.log("(persisted after refresh)") refresh_persist_timeout=null; },2000); }.bind(null,url)); } } module.exports=function(app,io,_moddir){ moddir=_moddir; app.all(["/changes","/changes/*"],cmn.authgen()); app.get("/changes",function(req,res){ res.sendFile(moddir+"/changes.html"); }); app.get("/changes/urls",function(req,res){ var list=[]; var url; for(url in urls)list.push(url); res.send(JSON.stringify(list)); }); app.get("/changes/url",function(req,res){ var url=req.query.url; if(!urls[url]){ res.status(404); res.send("URL not found in watch list"); return; } res.send(JSON.stringify(urls[url])); }); app.post("/changes/url",function(req,res){ var url=req.body; urls[url]=new URLobject(url); persist.setItemSync("urls",urls); // refreshURLs(); res.send(); }); app.delete("/changes/url",function(req,res){ var url=req.body; if(!urls[url]){ res.status(404); res.send("URL not found in watch list"); return; } delete urls[url]; persist.setItemSync("urls",urls); res.send(); }); app.delete("/changes/url/delete",function(req,res){ var param; try {param=JSON.parse(req.body);} catch(e){ res.status(400); res.send("Invalid JSON sent"); } var url=param.url; var todate=new Date(param.todate); if(!urls[url]){ res.status(404); res.send("URL not found in watch list"); return; } if(todate.getTime()==NaN){ res.status(400); res.send("Invalid time sent"); } var tl=urls[url].timeline; var i; for(i=0;i