diff --git a/404.html b/404.html new file mode 100644 index 0000000..5f8a0a4 --- /dev/null +++ b/404.html @@ -0,0 +1,39 @@ + + + + EasyForm + + + + + + + + + + + + + +

Hello there! Feel free to post your message/comment/query to me

+
+ +
+
+ +
+
+ +
+ +
+ + +
+ + + + + diff --git a/app/bg-worker.js b/app/bg-worker.js index 61a68be..17be65d 100644 --- a/app/bg-worker.js +++ b/app/bg-worker.js @@ -11,7 +11,7 @@ function urlEncoded2Json(str){ for (let el of arr) { let elArray = el.split('='); let val = decodeURIComponent(elArray[1].replace( /\+/g, ' ' )).replace(/"/g,'\\"'); // Decoded and escaped - eval('obj.' + elArray[0] +'="' + val +'"'); + eval(`obj.${elArray[0]}="${val}"`); } return JSON.stringify(obj); @@ -29,7 +29,7 @@ async function pollApi(getFrom, postTo, TGchatID) { if (! response.ok) { errLvl = 1; // Set error to critical/fatal - throw "GET @ " + getFrom + " status: " + response.status; + throw `GET @ ${getFrom} status: ${response.status}`; } data = urlEncoded2Json(await response.text()); @@ -37,7 +37,7 @@ async function pollApi(getFrom, postTo, TGchatID) { postMessage([data, 0]); } catch (error) { - console.error(Date() + ': Error making GET request --', error); + console.error(`${Date()}: Error making GET request -- ${error}`); // Send error to main for logging. Error level: 1 for high priority / fatal. postMessage(['Failed to fetch form data.', errLvl]); return; @@ -57,17 +57,17 @@ async function pollApi(getFrom, postTo, TGchatID) { }) if (! response.ok) { - throw "POST @ " + postTo + " status: " + response.status +". Is chat ID = " + TGchatID + " ok?"; + throw `POST @ ${postTo} status: ${response.status}. Is chat ID = ${TGchatID} ok?`; } } catch (error) { - console.error(Date() + ': Error making POST request --', error); + console.error(`${Date()}: Error making POST request -- ${error}`); // Send error to main for logging. Error level: 2 for low priority / non-fatal. postMessage(['Failed to post form data to Telegram.', errLvl]); return; } - console.log(Date() + ": Relay complete."); + console.log(`${Date()}: Relay complete.`); }; relay(); // Start the first relay diff --git a/app/server.js b/app/server.js index 541bf14..3d93ded 100644 --- a/app/server.js +++ b/app/server.js @@ -1,7 +1,8 @@ // Main entry point for the server. Deploys background worker in "bg-worker.js" for handling networking. +spaHide("jsAlert"); + let myWorker = null; -let getFrom, postTo, TGchatID; let numReadMsgs = 0; let numTotalMsgs = 0; const logs = document.getElementById("logs"); @@ -9,7 +10,7 @@ const toggleServer = document.getElementById("toggleServer"); function logThis(report) { const row = document.createElement("p"); - row.append(Date() + ": " + report); + row.append(`${Date()}: ${report}`); logs.prepend(row); } @@ -37,7 +38,7 @@ function inbox(json){ const cell = document.createElement("td"); // Create a text entry: - entry = eval("data." + keysEnumArray[key]); + entry = eval(`data.${keysEnumArray[key]}`); // Append entry to cell: cell.append(entry); @@ -70,16 +71,22 @@ function genUUID() { } const fetchChatID = async () => { - logThis("Fetching Telegram chat ID") - const apiEndpoint = 'https://api.telegram.org/bot' + document.getElementById("apiKey").value + '/getUpdates'; + logThis("Fetching Telegram chat ID"); + const apiEndpoint = 'https://api.telegram.org/bot' + document.getElementById("TGbotKey").value + '/getUpdates'; const response = await fetch(apiEndpoint); // Make request if (! response.ok) { - logThis("Telegram API status code:" + response.status +". Is Bot API Token ok?"); + logThis(`Telegram API status code: ${response.status}. Is Bot API Token ok?`); alert("Failed to fetch chat ID. Check your Bot API Token!"); return; } const data = await response.json(); - document.getElementById("chatID").value = data.result[0].message.chat.id; + try { + const TGchatID = data.result[0].message.chat.id; + document.getElementById("chatID").value = TGchatID; + localStorage.setItem("TGchatID", TGchatID); + } catch (e) { + alert("Failed to fetch chat ID. Send any text to the Telegram Bot then try again."); + } } function config() { @@ -87,20 +94,22 @@ function config() { const uuid = document.getElementById("uuid").value; // Choose a random index in [0, relayList.length]. Use first two nibbles of uuid as random number in range [0,256]. const randomIdx = Math.floor(parseInt(uuid.substr(0,2),16)*relayList.length/256); - getFrom = relayList[randomIdx] + '/' + uuid; - postTo = 'https://api.telegram.org/bot' + document.getElementById("apiKey").value + '/sendMessage'; - TGchatID = document.getElementById("chatID").value; - document.getElementById("config").innerHTML = '

HTML Form Action URL: ' + getFrom + '

'; - document.getElementById("testFormBtn").setAttribute("formaction", getFrom); - spaShowHide("testForm"); - document.getElementById("config").scrollIntoView(); + const getFrom = relayList[randomIdx] + '/' + uuid; + localStorage.setItem("getFrom", getFrom); + const postTo = 'https://api.telegram.org/bot' + document.getElementById("TGbotKey").value + '/sendMessage'; + localStorage.setItem("postTo", postTo); + spaGoTo("server"); + localStorage.setItem("loggedIn", "true"); } function startWorker() { - if (getFrom === undefined) { - config(); + if (myWorker || sessionStorage.getItem("server")) { + alert('Another server is already running. Only one server can run at a time.'); + return; + } else { + sessionStorage.setItem("server", "live"); } - + myWorker = new Worker("app/bg-worker.js"); // Register handler for messages from the background worker @@ -109,29 +118,40 @@ function startWorker() { const msg = e.data[0]; if (! errLvl) { inbox(msg); - logThis('RECEIVED: ' + msg); + logThis(`RECEIVED: ${msg}`); } else if (errLvl === 1) { stopWorker(); - logThis('FATAL ERROR: ' + msg + ' See console for details.'); + logThis(`FATAL ERROR: ${msg}. See console for details.`); alert('Server stopped due to some critical error'); } else { - logThis('ERROR: ' + msg + ' See console for details.'); + logThis(`ERROR: ${msg}. See console for details.`); } } + const getFrom = localStorage.getItem("getFrom"); + // Communicate key data to the background worker - myWorker.postMessage([getFrom, postTo, TGchatID]); + myWorker.postMessage([getFrom, localStorage.getItem("postTo"), localStorage.getItem("TGchatID")]); toggleServer.value = "Kill Server"; toggleServer.disabled = false; logThis("Server started"); document.getElementById("serverStatus").innerHTML = 'Live '; + + document.getElementById("formActionURL").innerHTML = `

HTML Form Action URL: ${getFrom}

`; + document.getElementById("readyForm").href = `./${btoa(getFrom).replace(/\+/g,'_').replace(/\//g,'-')}`; + document.getElementById("testFormBtn").setAttribute("formaction", getFrom); + spaShow("testForm"); } function stopWorker() { + if (! myWorker) { + return; + } myWorker.terminate(); myWorker = null; + sessionStorage.removeItem("server"); console.log("Worker terminated"); toggleServer.value = "Launch Server" logThis("Server stopped"); @@ -145,3 +165,22 @@ function toggleWorker() { startWorker(); } } + +function signout() { + stopWorker(); + localStorage.clear(); + location.reload(); +} + +function main() { + // Enable config if no prior settings found in localStorage + if (localStorage.getItem("loggedIn")) { + startWorker(); + spaGoTo("server"); + } else { + spaGoTo("setup"); + } + +} + +spaHide("jsAlert"); diff --git a/app/spa.js b/app/spa.js index 27b8702..a092d5e 100644 --- a/app/spa.js +++ b/app/spa.js @@ -5,14 +5,30 @@ const spaHomePageID = document.querySelector(".spa-page").id; // Assuming first spa-page class is the home / hero page let spaCurrentPageID = spaHomePageID; -{ - const pages = document.getElementsByClassName("spa-page"); +function spaShow(id) { + document.getElementById(id).style.display = 'block'; +} - for (let el of pages) { - el.style.display = 'none'; +function spaHide(id) { + document.getElementById(id).style.display = 'none'; +} + +function spaToggle(id) { + let x = document.getElementById(id); + if (x.style.display === "none") { + x.style.display = "block"; + } else { + x.style.display = "none"; } } +function spaGoTo(id) { + document.getElementById(spaCurrentPageID).style.display = 'none'; + spaShow(id); + spaCurrentPageID = id; + spaTop(); +} + function spaTop(){ document.getElementById(spaCurrentPageID).scrollIntoView(); } @@ -21,19 +37,11 @@ function spaBottom(){ document.getElementById(spaCurrentPageID).scrollIntoView(false); } -function spaGoTo(id) { - document.getElementById(spaCurrentPageID).style.display = 'none'; - document.getElementById(id).style.display = 'block'; - spaCurrentPageID = id; - spaTop(); -} +{ + const pages = document.getElementsByClassName("spa-page"); -function spaShowHide(id) { - let x = document.getElementById(id); - if (x.style.display === "none") { - x.style.display = "block"; - } else { - x.style.display = "none"; + for (let el of pages) { + el.style.display = 'none'; } } diff --git a/index.html b/index.html index b1f5087..04da7fe 100755 --- a/index.html +++ b/index.html @@ -22,11 +22,9 @@

Welcome to EasyForm

-

Menu

- - + Source Donate Contact @@ -39,43 +37,35 @@

Menu

Server: None yet
+ + +

You don't have JavaScript enabled! This page cannot function without it.

+

About

-

EasyForm gives you a free and easy, self-hosted form backend solution for adding (contact) forms to your static website(s). You don't, however, need - to configure any server or install anything. Your browser becomes your server! -

-

Your smartphone or PC is perhaps always connected to the internet, even on the move. So, if you keep your browser open there, and a very - light-weight JavaScript server runs in it, you are essentially "self-hosting" for free. EasyForm capitalizes on this. Also, the ability to run in a - browser makes EasyForm platform-independent! +

EasyForm gives you a free and easy, self-hosted form backend solution that runs in your browser! Just sign up and then embed the following HTML + form in your website. You also get your own contact form URL that you can use if you don't have a website.

- Working with EasyForm is dead simple. All you need to do is the following: -
    -
  • Create a Telegram Bot and store its API token. This is easy. Just open a chat with @BotFather in Telegram - and send: /newbot -
  • -
  • Follow instructions in the Config: section below. You will be required to choose a Form Action URL there
  • -
  • Use your chosen Form Action URL in your (contact) form
  • -
- Whenever your users submit the form, you will get a Telegram text containing the users' form data from the Telegram Bot you created. -

Here is an HTML code snippet you can readily embed as a basic contact form in your website. Just replace FormActionURL with the actual URL.


-<form action="FormActionURL" method="POST" target="hidden_iframe" autocomplete="on">
+<!-- Replace XXXXX with the form action URL given by this app upon sign up` -->
+<form action="XXXXX" method="POST" target="hidden_iframe">
     <input type="hidden" name="From" value="sample">
     <input type="email" name="Email" placeholder="Your Email">
     <input type="text" name="Name" placeholder="Your Name">
-    <input type="text" name="Message" placeholder="Your Message" autocomplete="off">
-    <input type="submit" value="Submit">
-    <input type="reset" value="Reset">
+    <input type="text" name="Message" placeholder="Your Message">
+    <button type="submit">Submit<button>
+    <input type="reset">Reset<button>
 </form>
 <!-- when the form is submitted, the server response will appear in this iframe, hidden from view -->
 <iframe name="hidden_iframe" src="about:blank" hidden></iframe>
 
- Tips: -
    -
  • Securely store your Bot API token and Form Action URL for future reference.
  • -
  • For reproducibility upon page reload/refresh, reuse the previous values, often suggested by the browser, during config.
  • -
+

As long as this Tab is open in your browser, whenever your users submit the form, your Inbox here will be populated. + You will also be notified via Telegram. +

+ +

+

Powered by

-
+
-

Server

-
-
+

Setup

+

Setup in just 3 easy steps.

- - + +
-

2. Send any text to the Bot. Then, click Fetch Chat ID. Or, enter your chat ID if you know what you're doing :-)

+

2. Send any text to the Bot. Then, click Fetch Chat ID. Do not enter your chat ID by hand.

- +

3. Generate or enter your EasyForm API Key:



- +
-
-
+
+
+
+

Server

+
+
+

Test if everything is working properly with the following sample form (embed in your own website with + ). You should get a Telegram message upon clicking Post! Your posted data + should also be logged below.

+

You also get your own contact form URL.

@@ -129,11 +126,14 @@

Server



Log

+ + + +

Server logs will be shown here



-