var profileWebsocket, selfWebsocket,profileServerStatus; var profiles; var profileID, privKey, selfID; function viewProfile(){ if( sessionStorage.profiles === undefined || sessionStorage.privKey === undefined || sessionStorage.selfID === undefined || sessionStorage.serverPass === undefined){ alert("Login credentials failed! Returning to home page!"); window.location.href = "home.html"; return; } profiles = JSON.parse(sessionStorage.profiles); console.log(profiles); privKey = encrypt.retrieveShamirSecret(JSON.parse(sessionStorage.privKey)); selfID = sessionStorage.selfID; var url = new URL(window.location.href); profileID = url.searchParams.get("floID"); superNodeList = JSON.parse(sessionStorage.superNodeList); kBucketObj.launchKBucket().then(function(result){ console.log(result) listProfiles(); displayProfile(profileID); }).catch(function(error){ console.log(error.message); }); } function displayProfile(profileID){ console.log(profileID); var errorMsg; if(!profileID) errorMsg = "Select a Profile to display"; else if(!validateAddr(profileID)) errorMsg = "Invalid FLO ID"; else if(!(profileID in profiles)) errorMsg = "FLO ID not registered to FLO Tweet"; if(errorMsg !== undefined){ document.getElementById("profileBody").innerHTML = errorMsg; return; } console.log("displayProfile"); document.getElementById("profileName").innerHTML=profiles[profileID].name; document.getElementById("profileFloID").innerHTML='@'+profileID; initselfWebSocket(); displayTweetFromIDB(profileID).then(function(result){ connectToX(profileID).then(function(result){ console.log(result); profileServerStatus = true; getTweetsFromX(profileID); }).catch(function(error){ console.log(error); pingSuperNodeforNewTweets(profileID); profileServerStatus = false; }); }).catch(function(error){ console.log(error.message); }); } function displayTweetFromIDB(floID){ return new Promise( function(resolve,reject){ var idb = indexedDB.open("FLO_Tweet"); idb.onerror = function(event) { reject("Error in opening IndexedDB!"); }; idb.onsuccess = function(event) { var db = event.target.result; var obj = db.transaction("following", "readwrite").objectStore("following"); obj.get(floID).onsuccess = function (event) { var followBtn = document.getElementById("follow-button"); if(event.target.result === undefined){ followBtn.innerHTML = "+ Follow"; followBtn.value = "follow"; }else{ followBtn.innerHTML = "- Unfollow"; followBtn.value = "unfollow"; } followBtn.disabled = false; } var obs = db.transaction("tweets", "readwrite").objectStore("tweets"); obs.openCursor().onsuccess = function(event) { var cursor = event.target.result; if(cursor) { //console.log(cursor.value) if(cursor.value.floID == floID) createTweetElement(floID,cursor.value.time,cursor.value.data); cursor.continue(); }else{ resolve("Displayed Tweets from IDB!"); } } db.close(); }; } ); } function createTweetElement(floID,time,tweet){ var tweetDisplay = document.getElementById("profileBody"); var element = document.createElement("div"); element.setAttribute("class", "media"); element.innerHTML = `

${profiles[floID].name} @${floID}

${tweet}

`; tweetDisplay.insertBefore(element, tweetDisplay.firstChild); } function connectToX(floID){ return new Promise( function(resolve,reject){ profileWebsocket = new WebSocket("ws://"+profiles[floID].onionAddr+"/ws"); profileWebsocket.onopen = function(ev){ resolve("Connected to Profile Server!"); }; profileWebsocket.onerror = function(ev) { reject("Profile Server is offline!"); }; profileWebsocket.onclose = function(ev) { console.log("Disconnected from Profile Server!") }; profileWebsocket.onmessage = function(evt){ console.log(evt.data); try{ var data = JSON.parse(evt.data); var id = data.id; data = data.data; if( floID!=data.floID || !encrypt.verify(data.tweet,data.sign,profiles[floID].pubKey)) return storeTweet({floID:floID,time:data.time,data:data.tweet},id); createTweetElement(floID,data.time,data.tweet); }catch(error){ console.log(error.message); } } } ); } function storeTweet(data,id){ var idb = indexedDB.open("FLO_Tweet"); idb.onerror = function(event) { console.log("Error in opening IndexedDB!"); }; idb.onsuccess = function(event) { var db = event.target.result; var obs = db.transaction("tweets", "readwrite").objectStore("tweets"); data.id = `${data.time}_${data.floID}`; obs.add(data); var obsL = db.transaction("lastTweet", "readwrite").objectStore("lastTweet"); obsL.put(id,data.floID); db.close(); }; } function pingSuperNodeforNewTweets(floID){ getLastTweetCount(floID).then(function(result){ var data = JSON.stringify({reqNewTweets:true,floID:floID,tid:result,requestor:selfID}) sendDataToSuperNode(floID,data); }).catch(function(error){ console.log(error.message); }); } function getTweetsFromX(floID){ return new Promise( function (resolve,reject){ getLastTweetCount(floID).then(function(result){ console.log(profileWebsocket); profileWebsocket.send(`>${result}`); console.log("sent"); resolve('Sent New tweet request to user server!'); }).catch(function(error){ console.log(error.message); }); } ); } function getLastTweetCount(floid){ return new Promise( function(resolve,reject){ var idb = indexedDB.open("FLO_Tweet"); idb.onsuccess = function(event) { var db = event.target.result; var lastTweet = db.transaction('lastTweet', "readwrite").objectStore('lastTweet'); var lastTweetReq = lastTweet.get(floid); lastTweetReq.onsuccess = function(event){ var result = event.target.result; if(result === undefined) result = 0; resolve(result); } db.close(); }; } ); } function initselfWebSocket(){ selfWebsocket = new WebSocket("ws://"+location.host+"/ws"); selfWebsocket.onopen = function(evt){ console.log("Connecting"); var serverPass = encrypt.retrieveShamirSecret(JSON.parse(sessionStorage.serverPass)); selfWebsocket.send("$"+serverPass); }; selfWebsocket.onclose = function(evt){ console.log("DISCONNECTED"); }; selfWebsocket.onmessage = function(evt){ console.log(evt.data); if(evt.data[0] == '$') return; try{ data = JSON.parse(evt.data); if(data.follow && encrypt.verify(selfID, data.sign, profiles[data.floID].pubKey)){ var idb = indexedDB.open("FLO_Tweet"); idb.onsuccess = function(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}-${data.sign}`); }else if(data.unfollow && encrypt.verify(selfID, data.sign, profiles[data.floID].pubKey)){ var idb = indexedDB.open("FLO_Tweet"); idb.onsuccess = function(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.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); } } }catch(error){ console.log(error.message) } }; selfWebsocket.onerror = function(evt){ console.log(evt); }; } function follow(){ var followBtn = document.getElementById("follow-button"); if(followBtn.value == 'follow'){ var sign = encrypt.sign(profileID,privKey); var data = JSON.stringify({follow:true, floID:selfID, sign:sign}); if(profileServerStatus) profileWebsocket.send(data); else{ var SNdata = JSON.stringify({viaSuperNodeMsg:true,from:selfID,to:profileID,data:data}) sendDataToSuperNode(profileID,SNdata) } selfWebsocket.send(`f${profileID}-${sign}`) var idb = indexedDB.open("FLO_Tweet"); idb.onsuccess = function(event) { var db = event.target.result; var obs = db.transaction("following", "readwrite").objectStore("following"); obs.add(sign,profileID); db.close(); }; followBtn.value = 'unfollow'; followBtn.innerHTML = "- Unfollow"; } else if(followBtn.value == 'unfollow'){ var sign = encrypt.sign(profileID,privKey); var data = JSON.stringify({unfollow:true, floID:selfID, sign:sign}); if(profileServerStatus) profileWebsocket.send(data); else{ var SNdata = JSON.stringify({viaSuperNodeMsg:true,from:selfID,to:profileID,data:data}) sendDataToSuperNode(profileID,SNdata) } selfWebsocket.send(`u${profileID}`) var idb = indexedDB.open("FLO_Tweet"); idb.onsuccess = function(event) { var db = event.target.result; var obs = db.transaction("following", "readwrite").objectStore("following"); obs.delete(profileID); db.close(); }; followBtn.value = 'follow'; followBtn.innerHTML = "+ Follow"; } }