The reload API data button (top-right) refreshes the API for new data The refreshed API data are added to memory as well as stored in IDB. The kBucket is reloaded
254 lines
9.5 KiB
JavaScript
254 lines
9.5 KiB
JavaScript
var profiles, following;
|
|
var selfWebsocket,followingWebSockets = [];
|
|
var privKey, modSuperNode, selfID;
|
|
|
|
function viewHome(){
|
|
if( sessionStorage.profiles === undefined || sessionStorage.privKey === undefined || sessionStorage.selfID === undefined || sessionStorage.serverPass === undefined || sessionStorage.superNodeList === undefined ){
|
|
alert("Login credentials failed! Returning to login page!");
|
|
window.location.href = "index.html";
|
|
return;
|
|
}
|
|
profiles = JSON.parse(sessionStorage.profiles);
|
|
console.log(profiles);
|
|
privKey = encrypt.retrieveShamirSecret(JSON.parse(sessionStorage.privKey));
|
|
selfID = sessionStorage.selfID;
|
|
superNodeList = new Set(JSON.parse(sessionStorage.superNodeList));
|
|
if(superNodeList.has(selfID))
|
|
modSuperNode = true;
|
|
kBucketObj.launchKBucket().then(result => {
|
|
console.log(result);
|
|
initselfWebSocket();
|
|
listProfiles();
|
|
pingSuperNodeforNewMsgs();
|
|
getFollowinglistFromIDB().then(result => {
|
|
following = result;
|
|
if(!following.includes(selfID))
|
|
following.push(selfID);
|
|
console.log(following);
|
|
displayTweetsFromIDB().then(result => {
|
|
connectToAllFollowing();
|
|
}).catch(error => {
|
|
console.log(error);
|
|
})
|
|
}).catch(error => {
|
|
console.log(error);
|
|
})
|
|
}).catch(error => {
|
|
console.log(error);
|
|
});
|
|
}
|
|
|
|
function initselfWebSocket(){
|
|
selfWebsocket = new WebSocket("ws://"+location.host+"/ws");
|
|
selfWebsocket.onopen = (event) => {
|
|
console.log("Connecting");
|
|
var serverPass = encrypt.retrieveShamirSecret(JSON.parse(sessionStorage.serverPass));
|
|
selfWebsocket.send("$"+serverPass);
|
|
};
|
|
selfWebsocket.onclose = (event) => { console.log("DISCONNECTED") };
|
|
selfWebsocket.onmessage = (event) => {
|
|
console.log(event.data);
|
|
if(event.data[0] == '$')
|
|
return;
|
|
try{
|
|
data = JSON.parse(event.data);
|
|
if(data.follow && encrypt.verify(selfID, data.sign, profiles[data.floID].pubKey)){
|
|
var idb = indexedDB.open("FLO_Tweet");
|
|
idb.onsuccess = (event) => {
|
|
var db = event.target.result;
|
|
var obs = db.transaction("followers", "readwrite").objectStore("followers");
|
|
obs.add(data.sign,data.floID);
|
|
db.close();
|
|
};
|
|
selfWebsocket.send(`F${data.floID}`);
|
|
}else if(data.unfollow && encrypt.verify(selfID, data.sign, profiles[data.floID].pubKey)){
|
|
var idb = indexedDB.open("FLO_Tweet");
|
|
idb.onsuccess = (event) => {
|
|
var db = event.target.result;
|
|
var obs = db.transaction("followers", "readwrite").objectStore("followers");
|
|
obs.delete(data.floID);
|
|
db.close();
|
|
};
|
|
selfWebsocket.send(`U${data.floID}`);
|
|
}else if(data.message && data.to == selfID){
|
|
var msg = encrypt.decryptMessage(data.secret,data.pubVal)
|
|
if(encrypt.verify(msg,data.sign,profiles[data.from].pubKey))
|
|
storeMsg({time:data.time,floID:data.from,text:msg,type:'R'});
|
|
}else if(data.fromSuperNode && following.includes(data.floID)){
|
|
var tid = data.tid;
|
|
data = JSON.parse(data.data);
|
|
if(encrypt.verify(data.tweet,data.sign,profiles[data.floID].pubKey)){
|
|
storeTweet({floID:data.floID,time:data.time,data:data.tweet},tid);
|
|
createTweetElement(data.floID,data.time,data.tweet);
|
|
}
|
|
}else if(modSuperNode){
|
|
superNodeMode(data);
|
|
}
|
|
}catch(error){
|
|
console.log(error);
|
|
}
|
|
};
|
|
selfWebsocket.onerror = (event) => { console.log(event) };
|
|
}
|
|
|
|
function listProfiles(){
|
|
console.log("listProfiles");
|
|
document.getElementById("profileName").innerHTML=profiles[selfID].name;
|
|
document.getElementById("profileFloID").innerHTML='@'+selfID;
|
|
var profileList = document.getElementById("profileList");
|
|
profileList.innerHTML = "";
|
|
for (p in profiles){
|
|
var element = document.createElement("div");
|
|
element.setAttribute("class", "media");
|
|
element.innerHTML = `<a href="profile.html?floID=${p}"><div class="media-body">
|
|
<h5 class="media-heading">${profiles[p].name}</h5>
|
|
<small>@${p}</small>
|
|
</div></a>`
|
|
profileList.appendChild(element);
|
|
}
|
|
}
|
|
|
|
function postTweet(){
|
|
var tweetBox = document.getElementById("tweetBox");
|
|
var tweet = tweetBox.value;
|
|
tweetBox.value = "";
|
|
var time = (new Date).getTime();
|
|
var sign = encrypt.sign(tweet,privKey);
|
|
var data = JSON.stringify({floID:selfID,time:time,tweet:tweet,sign:sign});
|
|
console.log(data);
|
|
selfWebsocket.send(data);
|
|
getLastTweetCount(selfID).then(result => {
|
|
var SNdata = JSON.stringify({newSuperNodeTweet:true,floID:selfID,tid:result+1,data:data});
|
|
sendDataToSuperNode(selfID,SNdata);
|
|
}).catch(error => {
|
|
console.log(error);
|
|
});
|
|
}
|
|
|
|
function getFollowinglistFromIDB(){
|
|
return new Promise((resolve,reject) => {
|
|
var idb = indexedDB.open("FLO_Tweet");
|
|
idb.onerror = (event) => { reject("Error in opening IndexedDB!") };
|
|
idb.onsuccess = (event) => {
|
|
var db = event.target.result;
|
|
var obs = db.transaction("following", "readwrite").objectStore("following");
|
|
var getReq = obs.getAllKeys();
|
|
getReq.onsuccess = (event) => { resolve(event.target.result) }
|
|
getReq.onerror = (event) => { reject('Unable to read following list!') }
|
|
db.close();
|
|
};
|
|
});
|
|
}
|
|
|
|
function displayTweetsFromIDB(){
|
|
return new Promise((resolve,reject) => {
|
|
var idb = indexedDB.open("FLO_Tweet");
|
|
idb.onerror = (event) => { reject("Error in opening IndexedDB!") };
|
|
idb.onsuccess = (event) => {
|
|
var db = event.target.result;
|
|
var obs = db.transaction("tweets", "readwrite").objectStore("tweets");
|
|
var curReq = obs.openCursor();
|
|
curReq.onsuccess = (event) => {
|
|
var cursor = event.target.result;
|
|
if(cursor) {
|
|
if(cursor.value.floID == selfID || following.includes(cursor.value.floID))
|
|
createTweetElement(cursor.value.floID,cursor.value.time,cursor.value.data);
|
|
cursor.continue();
|
|
}else{
|
|
resolve("Displayed Tweets from IDB!");
|
|
}
|
|
}
|
|
curReq.onerror = (event) => { reject("Error in Reading tweets from IDB!") }
|
|
db.close();
|
|
};
|
|
});
|
|
}
|
|
|
|
function createTweetElement(floID,time,tweet){
|
|
var tweetDisplay = document.getElementById("tweetsContainer");
|
|
var element = document.createElement("div");
|
|
element.setAttribute("class", "media");
|
|
element.innerHTML = `
|
|
<div class="media-body">
|
|
<h4 class="media-heading">${profiles[floID].name} <small>@${floID}</small></h4>
|
|
<p>${tweet.replace(/\n/g, "<br/>")}</p>
|
|
<ul class="nav nav-pills nav-pills-custom">
|
|
<li><a href="#"><span class="glyphicon glyphicon-share-alt"></span></a></li>
|
|
<li><a href="#"><span class="glyphicon glyphicon-retweet"></span></a></li>
|
|
<li><a href="#"><span class="glyphicon glyphicon-star"></span></a></li>
|
|
<li><a href="#"><span class="glyphicon glyphicon-option-horizontal"></span></a></li>
|
|
<li><span class="timestamp pull-right">${getTime(time)}</span></li>
|
|
</ul>
|
|
</div>`;
|
|
tweetDisplay.insertBefore(element, tweetDisplay.firstChild);
|
|
}
|
|
|
|
function connectToAllFollowing(){
|
|
console.log("Connecting to All following servers...")
|
|
following.forEach(floid => {
|
|
console.log(floid)
|
|
followingWebSockets[floid] = new WebSocket("ws://"+profiles[floid].onionAddr+"/ws");
|
|
|
|
followingWebSockets[floid].onopen = (event) => {
|
|
console.log(`Connected to ${floid} Server!`);
|
|
getLastTweetCount(floid).then(result => {
|
|
followingWebSockets[floid].send(`>${result}`);
|
|
}).catch(error => {
|
|
console.log(error);
|
|
});
|
|
};
|
|
followingWebSockets[floid].onerror = (event) => {
|
|
console.log(`${floid} Server is offline!`);
|
|
//Ping SuperNode for any new tweets
|
|
pingSuperNodeforNewTweets(floid);
|
|
};
|
|
followingWebSockets[floid].onclose = (event) => { console.log(`Disconnected from ${floid} Server!`); };
|
|
followingWebSockets[floid].onmessage = (event) => {
|
|
console.log(event.data);
|
|
try{
|
|
var data = JSON.parse(event.data);
|
|
var id = data.id;
|
|
data = data.data;
|
|
if( floid!=data.floID || !encrypt.verify(data.tweet,data.sign,profiles[floid].pubKey))
|
|
return
|
|
storeTweet({floID:data.floID,time:data.time,data:data.tweet},id);
|
|
createTweetElement(data.floID,data.time,data.tweet);
|
|
}catch(error){
|
|
console.log(error);
|
|
}
|
|
};
|
|
});
|
|
}
|
|
|
|
function getLastTweetCount(floid){
|
|
return new Promise((resolve,reject) => {
|
|
var idb = indexedDB.open("FLO_Tweet");
|
|
idb.onsuccess = (event) => {
|
|
var db = event.target.result;
|
|
var lastTweet = db.transaction('lastTweet', "readwrite").objectStore('lastTweet');
|
|
var lastTweetReq = lastTweet.get(floid);
|
|
lastTweetReq.onsuccess = (event) => {
|
|
var result = event.target.result;
|
|
if(result === undefined)
|
|
result = 0;
|
|
resolve(result);
|
|
}
|
|
db.close();
|
|
};
|
|
});
|
|
}
|
|
|
|
function pingSuperNodeforNewMsgs(){
|
|
var data = JSON.stringify({viaMsgreq:true,floID:selfID});
|
|
sendDataToSuperNode(selfID,data);
|
|
}
|
|
|
|
function pingSuperNodeforNewTweets(floID){
|
|
getLastTweetCount(floID).then(result => {
|
|
var data = JSON.stringify({reqNewTweets:true,floID:floID,tid:result,requestor:selfID})
|
|
sendDataToSuperNode(floID,data);
|
|
}).catch(error => {
|
|
console.log(error);
|
|
});
|
|
}
|