Skip to content

Instantly share code, notes, and snippets.

@sanity
Created September 17, 2022 16:16
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save sanity/59f0643a6891eab4ad304a87f987ce8c to your computer and use it in GitHub Desktop.
Save sanity/59f0643a6891eab4ad304a87f987ce8c to your computer and use it in GitHub Desktop.
<!doctype html>
<html>
<head>
<meta id="K_head" name="viewport" content="width=device-width, initial-scale=1.0">
<style>.rMStart {display: none;}
.rMStart {display: none;}
.rMEnd {display: none;}
.rLStart {display: none}
.rLEnd {display: none}
</style>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/toastify-js/src/toastify.min.css">
<script src="/static/jquery/jquery-3.4.1.min.js" crossorigin="anonymous"></script>
<link rel="stylesheet" type="text/css" href="/static/fomantic/semantic.min.css">
<script src="/static/fomantic/semantic.min.js"></script>
<meta id="K0" content="width=device-width, initial-scale=1" name="viewport">
<link id="K1" rel="stylesheet" href="/static/stripeCheckout/checkout.css">
<link id="K2" rel="stylesheet" href="/static/stripeCheckout/homepage.css">
<script id="K3" src="https://js.stripe.com/v3/"></script><script id="K4" src="/static/stripeCheckout/checkout.js"></script><script language="JavaScript">function toWSUrl(s) {
let l = window.location;
return (l.protocol === "https:" ? "wss://" : "ws://") + l.host + "/" + s;
}
let kwebClientId = "QI1ThR:wMfGCY";
let websocketEstablished = false;
let preWSMsgQueue = [];
let socket;
let bannerId = "CkU6vMWzW0Hbp" // Random id to avoid conflicts
let reconnectTimeout = 2000
//let reconnectCount = 0
let cachedFunctions = {
807868122 : function(auto_var_1,auto_var_2) {
window.addEventListener(auto_var_1, function(event) {
callbackWs(auto_var_2, {"type" : event.type, "retrieved" : (window.location.href)});
});
},
1778371595 : function(auto_var_1,auto_var_2) { document.getElementById(auto_var_1).textContent = auto_var_2; } };
function handleInboundMessage(msg) {
console.debug("")
const yourId = msg["yourId"];
const funcCalls = msg["functionCalls"]
for (let i = 0; i < funcCalls.length; i++) {
const funcCall = funcCalls[i];
const debugToken = funcCall["debugToken"];
if (kwebClientId != yourId) {
console.error(
"Received message from incorrect clientId, was " +
yourId +
", should be " +
kwebClientId
);
}
let func;
let js = funcCall["js"];
const args = funcCall["arguments"];
const params = funcCall["parameters"];
const cacheId = funcCall["jsId"];
const callbackId = funcCall["callbackId"];
if (cacheId !== undefined) {
if (cachedFunctions[cacheId] !== undefined) {
func = cachedFunctions[cacheId];
} else {
if (params !== undefined) {
func = new Function(params, js);
} else {
func = new Function(js);
}
cachedFunctions[cacheId] = func;
}
} else {
//This is a special case that doesn't bother reading the cache, or trying to cache the function.
//It will just run the javascript supplied to it. This special case is currently only used by Kweb.refreshPages()
if (params !== undefined) {
func = new Function(params, js);
} else {
func = new Function(js);
}
}
if (callbackId !== undefined) {
try {
const data = func.apply(this, args)
console.debug("Evaluated [ " + func.toString() + "]", data);
const callback = {callbackId: callbackId, data: data};
const message = {id: kwebClientId, callback: callback};
sendMessage(JSON.stringify(message));
} catch (err) {
debugErr(debugToken, err, "Error Evaluating `" + func.toString() + "`: " + err);
}
} else {
try {
func.apply(this, args);
console.debug("Executed Javascript", func.toString());
} catch (err) {
debugErr(debugToken, err, "Error Executing `" + func.toString() + "`: " + err);
}
}
}
}
function debugErr(debugToken, err, errMsg) {
if (debugToken !== undefined) {
console.error(errMsg);
const error = {
debugToken: debugToken,
error: {name: err.name, message: err.message}
};
const message = {id: kwebClientId, error: err};
sendMessage(JSON.stringify(message));
} else {
throw err;
}
}
function connectWs() {
var wsURL = toWSUrl("ws");
console.debug("Establishing websocket connection", wsURL);
socket = new WebSocket(wsURL);
if (window.WebSocket === undefined) {
document.body.innerHTML =
"<h1>Unfortunately this website requires a browser that supports websockets (all modern browsers do)</h1>";
console.error("Browser doesn't support window.WebSocket");
} else {
socket.onopen = function () {
console.debug("socket.onopen event received");
websocketEstablished = true;
console.debug("Websocket established", wsURL);
removeElementByIdIfExists(bannerId);
sendMessage(JSON.stringify({id: kwebClientId, hello: true}));
while (preWSMsgQueue.length > 0) {
sendMessage(preWSMsgQueue.shift());
}
reconnectTimeout = 2000
};
socket.onmessage = function (event) {
var msg = JSON.parse(event.data);
console.debug("Message received from socket: ", event.data);
handleInboundMessage(msg);
};
socket.onclose = function (evt) {
console.debug("Socket closed");
var explanation = "";
if (evt.reason && evt.reason.length > 0) {
explanation = "reason: " + evt.reason;
} else {
explanation = "without a reason specified";
}
if(evt.code == 1007){ //Server did restart or load balancer shifted session to other backend
location.reload(true);
}
console.error("WebSocket was closed", explanation, evt);
websocketEstablished = false;
setTimeout(() => {
reconnectLoopWs()
}, reconnectTimeout)
};
socket.onerror = function (evt) {
console.error("WebSocket error", evt);
websocketEstablished = false;
};
}
}
function reconnectLoopWs() {
reconnectTimeout *= 2
showReconnectToast();
setTimeout(function() {
if (websocketEstablished == false) {
if (reconnectTimeout < 600_000) {
console.log("Attempting to reconnect")
connectWs();
} else {
console.warn("Forcing page reload because the server is unresponsive for too long");
location.reload(true);
}
}
}, reconnectTimeout);
}
function showReconnectToast() {
Toastify({
text: `Connection to server lost, attempting to reconnect`,
duration: reconnectTimeout,
close: false,
gravity: "bottom",
position: "center",
stopOnFocus: false,
style: {
color: "#ff0033",
background: "white"
}
}).showToast();
}
function sendMessage(msg) {
if (websocketEstablished) {
console.debug("Sending WebSocket message", msg);
socket.send(msg);
} else {
preWSMsgQueue.push(msg);
}
}
function callbackWs(callbackId, data) {
const msg = JSON.stringify({
id: kwebClientId,
callback: {callbackId: callbackId, data: data}
});
sendMessage(msg);
}
function sendKeepalive() {
const msg = JSON.stringify({
id: kwebClientId,
keepalive: true
});
sendMessage(msg);
}
setInterval(sendKeepalive, 60*1000);
/*
* Utility functions
*/
function hasClass(el, className) {
if (el.classList) return el.classList.contains(className);
else
return !!el.className.render(new RegExp("(\\s|^)" + className + "(\\s|$)"));
}
class DiffPatchData {
constructor(prefixEndIndex, postfixOffset, diffString) {
this.prefixEndIndex = prefixEndIndex;
this.postfixOffset = postfixOffset;
this.diffString = diffString;
}
}
//Used by setValue() in prelude.kt to return the difference between 2 strings
function get_diff_changes(htmlInputElement) {
let newString = htmlInputElement.value;//reads the new string value from data-attribute data-value
let oldString = htmlInputElement.dataset.previousInput;//reads the oldString from the data-attribute data-previous-input
savePreviousInput(newString, htmlInputElement)//put the newString into the data attribute so it can be used as the oldString the next time this method is run
if (oldString == undefined) {//the first time this is run previous-input should be undefined so we just return the new string
return new DiffPatchData(0, 0, newString);
}
let commonPrefixEnd = 0;
let oldStringLastIndex = oldString.length - 1;
let newStringLastIndex = newString.length - 1;
let commonPostfixOffset = -1; //if the postFix value is set to -1, it means there is no match on the end of the string
let shorterStringLength = (oldString.length > newString.length) ? newString.length : oldString.length;
for (let i = 0; i < shorterStringLength; i++) {
if (oldString.charAt(i) === newString.charAt(i)) {
commonPrefixEnd = i+1;
} else break;
}
for(let offset = 0; offset < shorterStringLength - commonPrefixEnd; offset++) {
if (oldString.charAt(oldStringLastIndex - offset) === newString.charAt(newStringLastIndex - offset)) {
commonPostfixOffset = offset+1;
} else break;
}
return new DiffPatchData(commonPrefixEnd, commonPostfixOffset, newString.substring(commonPrefixEnd, newString.length - commonPostfixOffset));
}
//Used to save the previous value of an input field to a data-attribute
function savePreviousInput(previousInputString, htmlInputElement) {
htmlInputElement.dataset.previousInput = previousInputString
}
function removeElementByIdIfExists(id) {
var e = document.getElementById(id);
if (e) {
e.parentNode.removeChild(e);
}
}
var docCookies = {
getItem: function (sKey) {
if (!sKey || !this.hasItem(sKey)) {
return "__COOKIE_NOT_FOUND_TOKEN__";
}
return unescape(
document.cookie.replace(
new RegExp(
"(?:^|.*;\\s*)" +
escape(sKey).replace(/[\-\.\+\*]/g, "\\$&") +
"\\s*\\=\\s*((?:[^;](?!;))*[^;]?).*"
),
"$1"
)
);
},
setItem: function (sKey, sValue, vEnd, sPath, sDomain, bSecure) {
if (!sKey || /^(?:expires|max\-age|path|domain|secure)$/.test(sKey)) {
return;
}
var sExpires = "";
if (vEnd) {
switch (typeof vEnd) {
case "number":
sExpires = "; max-age=" + vEnd;
break;
case "string":
sExpires = "; expires=" + vEnd;
break;
case "object":
if (vEnd.hasOwnProperty("toGMTString")) {
sExpires = "; expires=" + vEnd.toGMTString();
}
break;
}
}
document.cookie =
escape(sKey) +
"=" +
escape(sValue) +
sExpires +
(sDomain ? "; domain=" + sDomain : "") +
(sPath ? "; path=" + sPath : "") +
(bSecure ? "; secure" : "");
},
removeItem: function (sKey) {
if (!sKey || !this.hasItem(sKey)) {
return;
}
var oExpDate = new Date();
oExpDate.setDate(oExpDate.getDate() - 1);
document.cookie =
encodeURIComponent(sKey) + "=; expires=" + oExpDate.toGMTString() + "; path=/";
},
hasItem: function (sKey) {
return new RegExp(
"(?:^|;\\s*)" + encodeURIComponent(sKey).replace(/[\-\.\+\*]/g, "\\$&") + "\\s*\\="
).test(document.cookie);
}
};
function buildPage() {
handleInboundMessage({"yourId":"QI1ThR:wMfGCY","functionCalls":[{"jsId":807868122,"js":"\n window.addEventListener(auto_var_1, function(event) {\n \n callbackWs(auto_var_2, {\"type\" : event.type, \"retrieved\" : (window.location.href)});\n });\n ","parameters":"auto_var_1,auto_var_2","callbackId":1107793409,"arguments":["popstate",1107793409]}]});
handleInboundMessage({"yourId":"QI1ThR:wMfGCY","functionCalls":[]});
handleInboundMessage({"yourId":"QI1ThR:wMfGCY","functionCalls":[{"jsId":1778371595,"js":"document.getElementById(auto_var_1).textContent = auto_var_2;","parameters":"auto_var_1,auto_var_2","arguments":["Ka","Freenet - Staging"]},{"jsId":1778371595,"arguments":["Kb","Declare your digital independence"]},{"jsId":1778371595,"arguments":["Kd","Freenet"]},{"jsId":1778371595,"arguments":["Ke","23 years ago we created the original Freenet, the first distributed, decentralized peer-to-peer network. It pioneered technologies like cryptographic contracts and small-world networks, and is still under active development.\n\n"]},{"jsId":1778371595,"arguments":["Kf","Today we’re building Locutus, which will make it easy for developers to create and deploy decentralized alternatives to today’s centralized tech companies. These decentralized apps will be easy to use, scalable, and secured through cryptography."]},{"jsId":1778371595,"arguments":["Kg","Locutus News"]},{"jsId":1778371595,"arguments":["Ki","5th September, 2022: Ian gave an interview (YouTube) to Louis Rossmann about Locutus"]},{"jsId":1778371595,"arguments":["Kj","16th July, 2022: Ian gave a talk (YouTube) on Decentralized Reputation and Trust in Locutus"]},{"jsId":1778371595,"arguments":["Kk","7th July, 2022: Ian gave an introductory talk (Youtube, Vimeo) on Locutus"]},{"jsId":1778371595,"arguments":["Kl","6th July, 2022: Locutus makes the front page of the r/cryptocurrency subreddit"]},{"jsId":1778371595,"arguments":["Km","18th April, 2022: Locutus makes the front page of the r/programming subreddit"]},{"jsId":1778371595,"arguments":["Kn","10th April, 2022: Locutus makes the front page of Hacker News"]},{"jsId":1778371595,"arguments":["Ko","27th March, 2022: Locutus makes the front page of the r/privacy subreddit"]},{"jsId":1778371595,"arguments":["Kp","Software"]},{"jsId":1778371595,"arguments":["Kr","Fred - The original Freenet software, first released in March 2000 and continuously developed since"]},{"jsId":1778371595,"arguments":["Ks","Locutus - A decentralized application layer for the Internet, first release expected September 2022"]},{"jsId":1778371595,"arguments":["Kt","Community"]},{"jsId":1778371595,"arguments":["Kv","r/freenet on Reddit"]},{"jsId":1778371595,"arguments":["Kx","Locutus"]},{"jsId":1778371595,"arguments":["Kz","Follow @freenetorg on Twitter for updates"]},{"jsId":1778371595,"arguments":["K10","Chat with us on Matrix"]},{"jsId":1778371595,"arguments":["K12","Fred"]},{"jsId":1778371595,"arguments":["K14","Follow @freenetproject"]},{"jsId":1778371595,"arguments":["K15","IRC: #freenet on libera"]},{"jsId":1778371595,"arguments":["K16","Support Us"]},{"jsId":1778371595,"arguments":["K18","Bitcoin: 3M3fbA7RDYdvYeaoR69cDCtVJqEodo9vth"]},{"jsId":1778371595,"arguments":["K19","Zcash: t1VHw1PHgzvMqEEd31ZBt3Vyy2UrG4J8utB"]},{"jsId":1778371595,"arguments":["K1a","Ethereum: 0x79158A5Dbd9C0737CB27411817BD2759f5b9a9Ae"]},{"jsId":1778371595,"arguments":["K1b","Paypal & others: link"]}]});
connectWs();
}
</script>
</head>
<body onload="buildPage()" id="K_body">
<noscript> This page is built with <a href="https://kweb.io/">Kweb</a>, which
requires JavaScript to be enabled.
</noscript>
<script src="https://cdn.jsdelivr.net/npm/toastify-js"></script><span id="K5" class="rMStart"></span>
<div id="K7" class="ui text center aligned container" background-color="e8e8e8">
<div id="K8" class="ui text left aligned container">
<div id="K9">
<h1 id="Ka" class="ui text"></h1>
<h2 id="Kb" class="ui text"></h2>
</div>
<br id="Kc">
<h2 id="Kd" class="ui text"></h2>
<p id="Ke" class="ui text"></p>
<p id="Kf" class="ui text"></p>
<h2 id="Kg" class="ui text"></h2>
<div id="Kh" class="ui bulleted list">
<div id="Ki" class="ui item"></div>
<div id="Kj" class="ui item"></div>
<div id="Kk" class="ui item"></div>
<div id="Kl" class="ui item"></div>
<div id="Km" class="ui item"></div>
<div id="Kn" class="ui item"></div>
<div id="Ko" class="ui item"></div>
</div>
<h2 id="Kp" class="ui text"></h2>
<div id="Kq" class="ui bulleted list">
<div id="Kr" class="ui item"></div>
<div id="Ks" class="ui item"></div>
</div>
<h2 id="Kt" class="ui text"></h2>
<div id="Ku" class="ui bulleted list">
<div id="Kv" class="ui item"></div>
<div id="Kw" class="ui item">
<p id="Kx"></p>
<div id="Ky" class="ui bulleted list">
<div id="Kz" class="ui item"></div>
<div id="K10" class="ui item"></div>
</div>
</div>
<div id="K11" class="ui item">
<p id="K12"></p>
<div id="K13" class="ui bulleted list">
<div id="K14" class="ui item"></div>
<div id="K15" class="ui item"></div>
</div>
</div>
</div>
<h2 id="K16" class="ui text"></h2>
<div id="K17" class="ui bulleted list">
<div id="K18" class="ui item"></div>
<div id="K19" class="ui item"></div>
<div id="K1a" class="ui item"></div>
<div id="K1b" class="ui item"></div>
</div>
</div>
</div>
<span id="K6" class="rMEnd"></span>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment