diff --git a/frontend/html/poll.html b/frontend/html/poll.html
new file mode 100644
index 0000000..13b5dfa
--- /dev/null
+++ b/frontend/html/poll.html
@@ -0,0 +1,13 @@
+
+
+
+
+
+ {{ TITLE }}
+
+
+
+ Welcome to poll.horse!
+ {{ POLL_TITLE }}
+
+
\ No newline at end of file
diff --git a/frontend/html/result.html b/frontend/html/result.html
new file mode 100644
index 0000000..326adec
--- /dev/null
+++ b/frontend/html/result.html
@@ -0,0 +1,13 @@
+
+
+
+
+
+ {{ TITLE }}
+
+
+
+ Welcome to poll.horse!
+ {{ POLL_TITLE }} - Result
+
+
\ No newline at end of file
diff --git a/package-lock.json b/package-lock.json
index 384041e..0e89ea7 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -13,6 +13,7 @@
"compression": "^1.7.4",
"cookie-parser": "^1.4.6",
"express": "^4.17.2",
+ "node-fetch": "^2.6.6",
"node-persist": "^3.1.0"
},
"devDependencies": {
@@ -24,6 +25,7 @@
"@types/fs-extra": "^9.0.13",
"@types/mocha": "^9.0.0",
"@types/node": "^16.11.10",
+ "@types/node-fetch": "^2.5.12",
"@types/node-persist": "^3.1.2",
"@typescript-eslint/eslint-plugin": "^5.4.0",
"@typescript-eslint/parser": "^5.4.0",
@@ -268,6 +270,16 @@
"integrity": "sha512-3aRnHa1KlOEEhJ6+CvyHKK5vE9BcLGjtUpwvqYLRvYNQKMfabu3BwfJaA/SLW8dxe28LsNDjtHwePTuzn3gmOA==",
"dev": true
},
+ "node_modules/@types/node-fetch": {
+ "version": "2.5.12",
+ "resolved": "https://registry.npmjs.org/@types/node-fetch/-/node-fetch-2.5.12.tgz",
+ "integrity": "sha512-MKgC4dlq4kKNa/mYrwpKfzQMB5X3ee5U6fSprkKpToBqBmX4nFZL9cW5jl6sWn+xpRJ7ypWh2yyqqr8UUCstSw==",
+ "dev": true,
+ "dependencies": {
+ "@types/node": "*",
+ "form-data": "^3.0.0"
+ }
+ },
"node_modules/@types/node-persist": {
"version": "3.1.2",
"resolved": "https://registry.npmjs.org/@types/node-persist/-/node-persist-3.1.2.tgz",
@@ -632,6 +644,12 @@
"node": "*"
}
},
+ "node_modules/asynckit": {
+ "version": "0.4.0",
+ "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz",
+ "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=",
+ "dev": true
+ },
"node_modules/balanced-match": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
@@ -853,6 +871,18 @@
"integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
"dev": true
},
+ "node_modules/combined-stream": {
+ "version": "1.0.8",
+ "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz",
+ "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==",
+ "dev": true,
+ "dependencies": {
+ "delayed-stream": "~1.0.0"
+ },
+ "engines": {
+ "node": ">= 0.8"
+ }
+ },
"node_modules/commander": {
"version": "8.3.0",
"resolved": "https://registry.npmjs.org/commander/-/commander-8.3.0.tgz",
@@ -1032,6 +1062,15 @@
"integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==",
"dev": true
},
+ "node_modules/delayed-stream": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz",
+ "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=",
+ "dev": true,
+ "engines": {
+ "node": ">=0.4.0"
+ }
+ },
"node_modules/depd": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz",
@@ -1537,6 +1576,20 @@
"integrity": "sha512-8/sOawo8tJ4QOBX8YlQBMxL8+RLZfxMQOif9o0KUKTNTjMYElWPE0r/m5VNFxTRd0NSw8qSy8dajrwX4RYI1Hw==",
"dev": true
},
+ "node_modules/form-data": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/form-data/-/form-data-3.0.1.tgz",
+ "integrity": "sha512-RHkBKtLWUVwd7SqRIvCZMEvAMoGUp0XU+seQiZejj0COz3RI3hWP4sCv3gZWWLjJTd7rGwcsF5eKZGii0r/hbg==",
+ "dev": true,
+ "dependencies": {
+ "asynckit": "^0.4.0",
+ "combined-stream": "^1.0.8",
+ "mime-types": "^2.1.12"
+ },
+ "engines": {
+ "node": ">= 6"
+ }
+ },
"node_modules/forwarded": {
"version": "0.2.0",
"resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz",
@@ -2198,6 +2251,17 @@
"node": ">= 0.6"
}
},
+ "node_modules/node-fetch": {
+ "version": "2.6.6",
+ "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.6.tgz",
+ "integrity": "sha512-Z8/6vRlTUChSdIgMa51jxQ4lrw/Jy5SOW10ObaA47/RElsAN2c5Pn8bTgFGWn/ibwzXTE8qwr1Yzx28vsecXEA==",
+ "dependencies": {
+ "whatwg-url": "^5.0.0"
+ },
+ "engines": {
+ "node": "4.x || >=6.0.0"
+ }
+ },
"node_modules/node-persist": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/node-persist/-/node-persist-3.1.0.tgz",
@@ -2791,6 +2855,11 @@
"node": ">=0.6"
}
},
+ "node_modules/tr46": {
+ "version": "0.0.3",
+ "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz",
+ "integrity": "sha1-gYT9NH2snNwYWZLzpmIuFLnZq2o="
+ },
"node_modules/ts-node": {
"version": "10.4.0",
"resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.4.0.tgz",
@@ -2968,6 +3037,20 @@
"node": ">= 0.8"
}
},
+ "node_modules/webidl-conversions": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz",
+ "integrity": "sha1-JFNCdeKnvGvnvIZhHMFq4KVlSHE="
+ },
+ "node_modules/whatwg-url": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz",
+ "integrity": "sha1-lmRU6HZUYuN2RNNib2dCzotwll0=",
+ "dependencies": {
+ "tr46": "~0.0.3",
+ "webidl-conversions": "^3.0.0"
+ }
+ },
"node_modules/which": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz",
@@ -3308,6 +3391,16 @@
"integrity": "sha512-3aRnHa1KlOEEhJ6+CvyHKK5vE9BcLGjtUpwvqYLRvYNQKMfabu3BwfJaA/SLW8dxe28LsNDjtHwePTuzn3gmOA==",
"dev": true
},
+ "@types/node-fetch": {
+ "version": "2.5.12",
+ "resolved": "https://registry.npmjs.org/@types/node-fetch/-/node-fetch-2.5.12.tgz",
+ "integrity": "sha512-MKgC4dlq4kKNa/mYrwpKfzQMB5X3ee5U6fSprkKpToBqBmX4nFZL9cW5jl6sWn+xpRJ7ypWh2yyqqr8UUCstSw==",
+ "dev": true,
+ "requires": {
+ "@types/node": "*",
+ "form-data": "^3.0.0"
+ }
+ },
"@types/node-persist": {
"version": "3.1.2",
"resolved": "https://registry.npmjs.org/@types/node-persist/-/node-persist-3.1.2.tgz",
@@ -3554,6 +3647,12 @@
"integrity": "sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw==",
"dev": true
},
+ "asynckit": {
+ "version": "0.4.0",
+ "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz",
+ "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=",
+ "dev": true
+ },
"balanced-match": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
@@ -3732,6 +3831,15 @@
"integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
"dev": true
},
+ "combined-stream": {
+ "version": "1.0.8",
+ "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz",
+ "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==",
+ "dev": true,
+ "requires": {
+ "delayed-stream": "~1.0.0"
+ }
+ },
"commander": {
"version": "8.3.0",
"resolved": "https://registry.npmjs.org/commander/-/commander-8.3.0.tgz",
@@ -3869,6 +3977,12 @@
"integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==",
"dev": true
},
+ "delayed-stream": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz",
+ "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=",
+ "dev": true
+ },
"depd": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz",
@@ -4269,6 +4383,17 @@
"integrity": "sha512-8/sOawo8tJ4QOBX8YlQBMxL8+RLZfxMQOif9o0KUKTNTjMYElWPE0r/m5VNFxTRd0NSw8qSy8dajrwX4RYI1Hw==",
"dev": true
},
+ "form-data": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/form-data/-/form-data-3.0.1.tgz",
+ "integrity": "sha512-RHkBKtLWUVwd7SqRIvCZMEvAMoGUp0XU+seQiZejj0COz3RI3hWP4sCv3gZWWLjJTd7rGwcsF5eKZGii0r/hbg==",
+ "dev": true,
+ "requires": {
+ "asynckit": "^0.4.0",
+ "combined-stream": "^1.0.8",
+ "mime-types": "^2.1.12"
+ }
+ },
"forwarded": {
"version": "0.2.0",
"resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz",
@@ -4749,6 +4874,14 @@
"resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.2.tgz",
"integrity": "sha512-hZXc7K2e+PgeI1eDBe/10Ard4ekbfrrqG8Ep+8Jmf4JID2bNg7NvCPOZN+kfF574pFQI7mum2AUqDidoKqcTOw=="
},
+ "node-fetch": {
+ "version": "2.6.6",
+ "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.6.tgz",
+ "integrity": "sha512-Z8/6vRlTUChSdIgMa51jxQ4lrw/Jy5SOW10ObaA47/RElsAN2c5Pn8bTgFGWn/ibwzXTE8qwr1Yzx28vsecXEA==",
+ "requires": {
+ "whatwg-url": "^5.0.0"
+ }
+ },
"node-persist": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/node-persist/-/node-persist-3.1.0.tgz",
@@ -5156,6 +5289,11 @@
"resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz",
"integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA=="
},
+ "tr46": {
+ "version": "0.0.3",
+ "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz",
+ "integrity": "sha1-gYT9NH2snNwYWZLzpmIuFLnZq2o="
+ },
"ts-node": {
"version": "10.4.0",
"resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.4.0.tgz",
@@ -5271,6 +5409,20 @@
"resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz",
"integrity": "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw="
},
+ "webidl-conversions": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz",
+ "integrity": "sha1-JFNCdeKnvGvnvIZhHMFq4KVlSHE="
+ },
+ "whatwg-url": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz",
+ "integrity": "sha1-lmRU6HZUYuN2RNNib2dCzotwll0=",
+ "requires": {
+ "tr46": "~0.0.3",
+ "webidl-conversions": "^3.0.0"
+ }
+ },
"which": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz",
diff --git a/package.json b/package.json
index f858101..f294bc4 100644
--- a/package.json
+++ b/package.json
@@ -40,6 +40,7 @@
"@types/fs-extra": "^9.0.13",
"@types/mocha": "^9.0.0",
"@types/node": "^16.11.10",
+ "@types/node-fetch": "^2.5.12",
"@types/node-persist": "^3.1.2",
"@typescript-eslint/eslint-plugin": "^5.4.0",
"@typescript-eslint/parser": "^5.4.0",
@@ -60,6 +61,7 @@
"compression": "^1.7.4",
"cookie-parser": "^1.4.6",
"express": "^4.17.2",
+ "node-fetch": "^2.6.6",
"node-persist": "^3.1.0"
}
}
diff --git a/src/Poll.ts b/src/Poll.ts
new file mode 100644
index 0000000..33ab9bb
--- /dev/null
+++ b/src/Poll.ts
@@ -0,0 +1,34 @@
+"use strict";
+
+type BasePoll = {
+ id: string,
+ title: string,
+ dupeCheckMode: "none" | "ip" | "cookie",
+ multiSelect: boolean,
+ captcha: boolean,
+ creationTime: Date,
+};
+type FrontendPoll = BasePoll & {
+ options: string[],
+ error?: string,
+};
+type BackendPoll = BasePoll & {
+ options: {
+ [option: string]: number
+ },
+ dupeData: null | string[] | string
+};
+type PollResult = {
+ title: string,
+ votes: {
+ [option: string]: number
+ },
+ error?: string
+};
+
+
+export {
+ FrontendPoll,
+ BackendPoll,
+ PollResult
+};
diff --git a/src/backend.ts b/src/backend.ts
index 7a8677f..d131f83 100644
--- a/src/backend.ts
+++ b/src/backend.ts
@@ -4,19 +4,7 @@ import { Router } from "express";
import persist from "node-persist";
import { program } from "commander";
import { resolve } from "path";
-
-type Poll = {
- id: string,
- title: string,
- options: {
- [option: string]: number
- },
- dupeCheckMode: "none" | "ip" | "cookie",
- dupeData: null | string[] | string,
- multiSelect: boolean,
- captcha: boolean,
- creationTime: Date,
-};
+import { BackendPoll as Poll } from "./Poll";
function randomString(length = 10, charset = "abcdefghjkmnpqrstuvwxyzABCDEFGHJKLMNPQRSTUVWXYZ23456789") {
let result = "";
diff --git a/src/frontend.ts b/src/frontend.ts
index 33a32c6..71575f7 100644
--- a/src/frontend.ts
+++ b/src/frontend.ts
@@ -3,6 +3,9 @@ import fs from "fs-extra";
import { resolve } from "path";
import { Transform as TransformStream, Stream } from "stream";
import { Router, Request, Response } from "express";
+import fetch from 'node-fetch';
+import { program } from "commander";
+import { FrontendPoll as Poll, PollResult } from "./Poll";
const RenderBuffer = new WeakMap();
const RenderReplacements = new WeakMap();
@@ -91,11 +94,37 @@ async function displayPage(req: Request, res: Response, htmlFilename: string, re
export default function init(router: Router): void {
router.get("/:id/r", async (req, res) => {
const id = req.params.id;
- res.redirect(`/`);
+ try {
+ const poll: PollResult = await fetch(
+ (program.opts().backendBaseUrl || "http://localhost:" + program.opts().port) + "/_backend/poll-result/" + id
+ ).then(r => r.json()) as PollResult;
+ if (!poll || poll.error) return res.redirect("/");
+ await displayPage(req, res, "result.html", {
+ "POLL_ID": id,
+ "POLL_TITLE": poll.title,
+
+ });
+ } catch (error) {
+ console.log(error);
+ res.redirect(`/`);
+ }
});
router.get("/:id", async (req, res) => {
const id = req.params.id;
- res.redirect(`/`);
+ try {
+ const poll: Poll = await fetch(
+ (program.opts().backendBaseUrl || "http://localhost:" + program.opts().port) + "/_backend/poll/" + id
+ ).then(r => r.json()) as Poll;
+ if (!poll || poll.error) return res.redirect("/");
+ await displayPage(req, res, "poll.html", {
+ "POLL_ID": id,
+ "POLL_TITLE": poll.title,
+
+ });
+ } catch (error) {
+ console.log(error);
+ res.redirect(`/`);
+ }
});
router.get("/", (req, res) => displayPage(req, res, "index.html"));
}
\ No newline at end of file