From 98de002e14b07304b1518bd9e8eac5d5f47d761f Mon Sep 17 00:00:00 2001
From: Enstrayed <48845980+Enstrayed@users.noreply.github.com>
Date: Sun, 31 Mar 2024 12:52:26 -0700
Subject: [PATCH 1/8] god why
---
routes/etyd.js | 39 ++++++++++++++++++++++++---------------
1 file changed, 24 insertions(+), 15 deletions(-)
diff --git a/routes/etyd.js b/routes/etyd.js
index 5ace98a..8c011ec 100644
--- a/routes/etyd.js
+++ b/routes/etyd.js
@@ -31,24 +31,26 @@ app.post("/etydwrite", (rreq,rres) => {
switch(rreq.body.action) {
case "set": // Write to db
-
if (rreq.body.random == true) {
- let workingTarget = makeRandomHex()
-
- db.get(`/${workingTarget}`).then(dbres => {
- if (dbres != null) {
- let workingTarget = makeRandomHex()
-
- db.get(`/${workingTarget}`).then(dbres => {
- if (dbres != null) {
- // well fuck
+ let workingTarget = makeRandomHex() // Make a random URL
+ db.get(`/${workingTarget}`).then(dbres => { // Check if it exists
+ if (dbres != null) { // If it does
+ let workingTarget = makeRandomHex() // Make a new one
+ db.get(`/${workingTarget}`).then(dbres => { // Check if *that* exists
+ if (dbres != null) { // If it does
+ // Then everything is dumb and pointless so just give up
+ console.log(`${rreq.get("cf-connecting-ip")} POST /etydwrite ACTION set returned 409 (Two attempts to find an open key failed)`)
rres.sendStatus(409)
-
+ } else { // if it doesnt then set the stupid key I hate this code so much why did I do this serverside this is so dumb
+ console.log(`${rreq.get("cf-connecting-ip")} POST /etydwrite ACTION set returned 200 KEY:${rreq.get("Authorization")} TARGET: ${workingTarget}`)
+ db.set(`/${workingTarget}`,rreq.body.value)
+ rres.send(`https://etyd.cc/${workingTarget}`)
}
})
} else {
+ console.log(`${rreq.get("cf-connecting-ip")} POST /etydwrite ACTION set returned 200 KEY:${rreq.get("Authorization")} TARGET: ${workingTarget}`)
db.set(`/${workingTarget}`,rreq.body.value)
rres.send(`https://etyd.cc/${workingTarget}`)
}
@@ -71,12 +73,18 @@ app.post("/etydwrite", (rreq,rres) => {
case "delete":
- db.get(`/${rreq.body.target}`).then(dbres => {
+ let workingTarget = rreq.body.target.replace("https://etyd.cc/","") // Sanitize input
+ if (workingTarget.startsWith("/")) {
+ workingTarget = workingTarget.slice(1)
+ }
+
+ db.get(`/${workingTarget}`).then(dbres => {
if (dbres == null) { //if key doesnt exist then log and return 400
- console.log(`${rreq.get("cf-connecting-ip")} POST /etydwrite ACTION delete returned 400 KEY:${rreq.get("Authorization")}`)
- rres.sendStatus(400)
+ console.log(`${rreq.get("cf-connecting-ip")} POST /etydwrite ACTION delete returned 404 KEY:${rreq.get("Authorization")} TARGET: ${workingTarget}`)
+ rres.sendStatus(404)
} else {
- db.del(`/${rreq.body.target}`)
+ console.log(`${rreq.get("cf-connecting-ip")} POST /etydwrite ACTION delete returned 200 KEY:${rreq.get("Authorization")} TARGET: ${workingTarget}`)
+ db.del(`/${workingTarget}`)
rres.sendStatus(200)
}
})
@@ -84,6 +92,7 @@ app.post("/etydwrite", (rreq,rres) => {
default:
+ console.log(`${rreq.get("cf-connecting-ip")} POST /etydwrite ACTION default returned 400 KEY:${rreq.get("Authorization")}`)
rres.sendStatus(400) // request json didnt include a valid action
break;
}
--
2.49.1
From 3b96e07d13a6e3d94f2a417cd1c02a2851d86281 Mon Sep 17 00:00:00 2001
From: Enstrayed <48845980+Enstrayed@users.noreply.github.com>
Date: Tue, 9 Apr 2024 15:02:16 -0700
Subject: [PATCH 2/8] working changes
---
.gitignore | 3 +-
Caddyfile | 21 ++++
etydFrontend/_static/etyd.js | 61 ++++++++++
etydFrontend/_static/index.css | 22 ++++
etydFrontend/index.html | 75 +++++++++++++
package-lock.json | 33 +++++-
package.json | 6 +-
routes/etyd.js | 198 ++++++++++++++++-----------------
8 files changed, 317 insertions(+), 102 deletions(-)
create mode 100644 Caddyfile
create mode 100644 etydFrontend/_static/etyd.js
create mode 100644 etydFrontend/_static/index.css
create mode 100644 etydFrontend/index.html
diff --git a/.gitignore b/.gitignore
index cf7c602..29b0255 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,2 +1,3 @@
node_modules/
-config.json
\ No newline at end of file
+config.json
+bun.lockb
\ No newline at end of file
diff --git a/Caddyfile b/Caddyfile
new file mode 100644
index 0000000..eb42a99
--- /dev/null
+++ b/Caddyfile
@@ -0,0 +1,21 @@
+:8082 {
+ reverse_proxy localhost:8081
+}
+
+:8083 {
+ @staticpaths {
+ path /
+ path /_static*
+ path /favicon.ico
+ }
+
+ handle @staticpaths {
+ root ./etydFrontend
+ file_server
+ }
+
+ handle /* {
+ rewrite * /etyd{uri}
+ reverse_proxy localhost:8081
+ }
+}
\ No newline at end of file
diff --git a/etydFrontend/_static/etyd.js b/etydFrontend/_static/etyd.js
new file mode 100644
index 0000000..5879b9d
--- /dev/null
+++ b/etydFrontend/_static/etyd.js
@@ -0,0 +1,61 @@
+//Firefox check
+window.onload = function() {
+ document.getElementById('resultfeed').value = "hii :3"
+ if (navigator.userAgent.includes("Firefox")) {
+ document.getElementById('resultfeed').value += `\nClipboard functionality does not work on Firefox.`
+ document.getElementById('clipboard1').disabled = true
+ document.getElementById('clipboard2').disabled = true
+ }
+}
+
+function makeRandomHex(amount) {
+ const characters = "1234567890abcdef"
+ let counter = 0
+ let result = ""
+ while (counter < amount) {
+ result += characters.charAt(Math.floor(Math.random() * characters.length))
+ counter += 1
+ }
+ return result
+}
+
+function randomUrlTick() {
+ if (document.getElementById("randomizationtoggle").checked == true) {
+ document.getElementById("targetfield").disabled = true
+ document.getElementById("targetfield").value = makeRandomHex(6)
+ } else {
+ document.getElementById("targetfield").disabled = false
+ document.getElementById("targetfield").value = null
+ }
+}
+
+function buttonCopyResult() {
+ navigator.clipboard.writeText(`${document.location.href}${document.getElementById("urlfield").value}`)
+}
+
+function buttonFillFromClipboard() {
+ navigator.clipboard.readText().then(res => {
+ document.getElementById("valuefield").value = res;
+ })
+}
+
+function postData() {
+ fetch("http://nrdesktop:8081/etydwrite", {
+ method: "POST",
+ mode: "cors",
+ headers: {
+ "Authorization": document.getElementById("authfield").value
+ },
+ body: JSON.stringify({
+ "target": document.getElementById("targetfield").value,
+ "value": document.getElementById("valuefield").value,
+ "action": document.getElementById("actiondropdown").value,
+ "random": document.getElementById("randomizationtoggle").checked
+ })
+ }).then(response => {
+ document.getElementById("resultfeed").value += `\n${response.status} ${response.body}`
+ }).catch(error => {
+ document.getElementById("resultfeed").value += `\nError: ${error}`
+ })
+}
+
diff --git a/etydFrontend/_static/index.css b/etydFrontend/_static/index.css
new file mode 100644
index 0000000..cf34de1
--- /dev/null
+++ b/etydFrontend/_static/index.css
@@ -0,0 +1,22 @@
+body {
+ font-family: Arial, Helvetica, sans-serif;
+}
+
+.flexbox {
+ display: flex;
+ flex-wrap: wrap;
+}
+
+.marginright1em {
+ margin-right: 1em;
+}
+
+.resultfeed {
+ height: 100%;
+}
+
+@media (max-width: 700px) {
+ .resultfeed {
+ min-height: 20vh;
+ }
+}
\ No newline at end of file
diff --git a/etydFrontend/index.html b/etydFrontend/index.html
new file mode 100644
index 0000000..d210c0d
--- /dev/null
+++ b/etydFrontend/index.html
@@ -0,0 +1,75 @@
+
+
+
+
+
+
+ etyd.cc
+
+
+
+
etyd.cc URL Shortener
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Instructions
+
+ 1. Enter your API Key in the 'Authorization' field
+ 2. Enter the shortened URL you want to act upon under the 'URL' field
+ 3. Enter the URL that the user will be redirected to under the 'Value' field
+ 4. Change 'Action' depending if you want to create or delete a URL
+ 5. Press 'POST Data' to submit the form to the server
+
+
+
+
+
Status Code Reference
+
+ 400: Bad Request - You will see this if you try and delete a non-existent URL
+ 401: Unauthorized - Did you enter your API key?
+ 405: Method Not Allowed - You will see this if you try a request with no arguments
+ 409: Conflict - The entered URL already exists, tick 'Random' and try again
+ 500: Internal Server Error - If this happens something has gone very wrong
+ 502: Bad Gateway - If you see this the backend is down/unreachable by Caddy
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/package-lock.json b/package-lock.json
index 21f47ad..43da3b4 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -9,7 +9,20 @@
"version": "1.0.0",
"license": "UNLICENSED",
"dependencies": {
- "express": "^4.18.2"
+ "express": "^4.18.2",
+ "typescript": "^5.4.3"
+ },
+ "devDependencies": {
+ "@types/node": "^20.12.3"
+ }
+ },
+ "node_modules/@types/node": {
+ "version": "20.12.3",
+ "resolved": "https://registry.npmjs.org/@types/node/-/node-20.12.3.tgz",
+ "integrity": "sha512-sD+ia2ubTeWrOu+YMF+MTAB7E+O7qsMqAbMfW7DG3K1URwhZ5hN1pLlRVGbf4wDFzSfikL05M17EyorS86jShw==",
+ "dev": true,
+ "dependencies": {
+ "undici-types": "~5.26.4"
}
},
"node_modules/accepts": {
@@ -666,6 +679,24 @@
"node": ">= 0.6"
}
},
+ "node_modules/typescript": {
+ "version": "5.4.3",
+ "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.4.3.tgz",
+ "integrity": "sha512-KrPd3PKaCLr78MalgiwJnA25Nm8HAmdwN3mYUYZgG/wizIo9EainNVQI9/yDavtVFRN2h3k8uf3GLHuhDMgEHg==",
+ "bin": {
+ "tsc": "bin/tsc",
+ "tsserver": "bin/tsserver"
+ },
+ "engines": {
+ "node": ">=14.17"
+ }
+ },
+ "node_modules/undici-types": {
+ "version": "5.26.5",
+ "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz",
+ "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==",
+ "dev": true
+ },
"node_modules/unpipe": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz",
diff --git a/package.json b/package.json
index 9b134b7..01392d7 100644
--- a/package.json
+++ b/package.json
@@ -18,5 +18,9 @@
"bugs": {
"url": "https://github.com/enstrayed/enstrayedapi/issues"
},
- "homepage": "https://api.enstrayed.com"
+ "homepage": "https://api.enstrayed.com",
+ "devDependencies": {
+ "@types/bun": "^1.0.12",
+ "@types/node": "^20.12.3"
+ }
}
diff --git a/routes/etyd.js b/routes/etyd.js
index 8c011ec..140eb16 100644
--- a/routes/etyd.js
+++ b/routes/etyd.js
@@ -1,108 +1,108 @@
const { app, db, globalConfig } = require("../index.js") // Get globals from index
-function makeRandomHex() {
- const characters = "1234567890abcdef"
- let counter = 0
- let result = ""
- while (counter < globalConfig.etyd.randomHexLength) {
- result += characters.charAt(Math.floor(Math.random() * characters.length))
- counter += 1
- }
- return result
-}
+// 2024-04-05: Unused because trying to put randomization server side just made no sense
+// function makeRandomHex() {
+// const characters = "1234567890abcdef"
+// let counter = 0
+// let result = ""
+// while (counter < globalConfig.etyd.randomHexLength) {
+// result += characters.charAt(Math.floor(Math.random() * characters.length))
+// counter += 1
+// }
+// return result
+// }
-app.options("/etydwrite", (rreq,rres) => {
- rres.set("Access-Control-Allow-Headers","Authorization")
- rres.set("Access-Control-Allow-Origin","*")
- rres.sendStatus(204)
-})
+// 2024-04-05: Defining OPTIONS for browser prefetch is no longer necessary as CORS is not going to be used
+// app.options("/etydwrite", (rreq,rres) => {
+// rres.set("Access-Control-Allow-Headers","Authorization")
+// rres.set("Access-Control-Allow-Origin","*")
+// rres.sendStatus(204)
+// })
-app.post("/etydwrite", (rreq,rres) => {
- db.get(globalConfig.etyd.authKeyInDb).then(dbres => {
-
- if (dbres == null) { // If authkey key doesnt exist in redis then error out
- console.log("ERROR: Configured key containing etyd authkeys is null")
- rres.sendStatus(500)
- } else { // if it does exist
- let validKeys = dbres.split(",") // split the string into an array
- if (validKeys.includes(rreq.get("Authorization"))) { // check if authorization header key exists in that array
-
- console.log(rreq.body)
-
- switch(rreq.body.action) {
- case "set": // Write to db
- if (rreq.body.random == true) {
-
- let workingTarget = makeRandomHex() // Make a random URL
- db.get(`/${workingTarget}`).then(dbres => { // Check if it exists
- if (dbres != null) { // If it does
- let workingTarget = makeRandomHex() // Make a new one
- db.get(`/${workingTarget}`).then(dbres => { // Check if *that* exists
- if (dbres != null) { // If it does
- // Then everything is dumb and pointless so just give up
- console.log(`${rreq.get("cf-connecting-ip")} POST /etydwrite ACTION set returned 409 (Two attempts to find an open key failed)`)
- rres.sendStatus(409)
- } else { // if it doesnt then set the stupid key I hate this code so much why did I do this serverside this is so dumb
- console.log(`${rreq.get("cf-connecting-ip")} POST /etydwrite ACTION set returned 200 KEY:${rreq.get("Authorization")} TARGET: ${workingTarget}`)
- db.set(`/${workingTarget}`,rreq.body.value)
- rres.send(`https://etyd.cc/${workingTarget}`)
- }
- })
-
- } else {
- console.log(`${rreq.get("cf-connecting-ip")} POST /etydwrite ACTION set returned 200 KEY:${rreq.get("Authorization")} TARGET: ${workingTarget}`)
- db.set(`/${workingTarget}`,rreq.body.value)
- rres.send(`https://etyd.cc/${workingTarget}`)
- }
- })
-
- } else {
-
- db.get(rreq.body.target).then(dbres => { // check if key already exists
- if (dbres != null) { // if it does then send 409 conflict
- console.log(`${rreq.get("cf-connecting-ip")} POST /etydwrite ACTION set returned 409 KEY:${rreq.get("Authorization")}`)
- rres.sendStatus(409)
- } else {
- db.set(`/${rreq.body.target}`,rreq.body.value)
- rres.send(`https://etyd.cc/${rreq.body.target}`)
- }
- })
-
- }
- break;
-
-
- case "delete":
- let workingTarget = rreq.body.target.replace("https://etyd.cc/","") // Sanitize input
- if (workingTarget.startsWith("/")) {
- workingTarget = workingTarget.slice(1)
- }
-
- db.get(`/${workingTarget}`).then(dbres => {
- if (dbres == null) { //if key doesnt exist then log and return 400
- console.log(`${rreq.get("cf-connecting-ip")} POST /etydwrite ACTION delete returned 404 KEY:${rreq.get("Authorization")} TARGET: ${workingTarget}`)
- rres.sendStatus(404)
- } else {
- console.log(`${rreq.get("cf-connecting-ip")} POST /etydwrite ACTION delete returned 200 KEY:${rreq.get("Authorization")} TARGET: ${workingTarget}`)
- db.del(`/${workingTarget}`)
- rres.sendStatus(200)
- }
- })
- break;
-
-
- default:
- console.log(`${rreq.get("cf-connecting-ip")} POST /etydwrite ACTION default returned 400 KEY:${rreq.get("Authorization")}`)
- rres.sendStatus(400) // request json didnt include a valid action
- break;
- }
-
- } else { // if it doesnt then its a unauthorized request
- console.log(`${rreq.get("cf-connecting-ip")} POST /etydwrite returned 401`)
- rres.sendStatus(401)
- }
+app.get("/etyd*", (rreq,rres) => {
+ fetch(`http://${globalConfig.couchdb.host}/etyd${rreq.path.replace("/etyd","")}`, {
+ headers: {
+ "Authorization": `Basic ${btoa(globalConfig.couchdb.authorization)}`
}
+ }).then(dbRes => {
+ if (dbRes.status == 404) {
+ rres.sendStatus(404)
+ } else {
+ dbRes.json().then(dbRes => {
+ rres.redirect(dbRes.content.url)
+ })
+ }
+ }).catch(fetchError => {
+ rres.sendStatus(500)
+ console.log(`${rres.get("cf-connecting-ip")} GET ${rreq.path} returned 500: ${fetchError}`)
})
})
+app.delete("/etyd*", (rreq,rres) => {
+
+ fetch(`http://${globalConfig.couchdb.host}/apiauthkeys/${globalConfig.etyd.authKeysDoc}`, {
+ headers: {
+ "Authorization": `Basic ${btoa(globalConfig.couchdb.authorization)}`
+ }
+ }).then(dbRes => dbRes.json()).then(dbRes => {
+
+ if (dbRes.status == 404) { // If document containing cider auth keys does not exist
+ console.log(`ERROR: Could not find apiauthkeys/${globalConfig.etyd.authKeysDoc}`)
+ rres.sendStatus(500) // Refuse request
+ } else {
+ if (rreq.get("Authorization") == null) { // If authorization header is not supplied
+ rres.sendStatus(400) // then return bad request (would return 500 otherwise)
+ } else {
+ if (dbRes["content"][rreq.get("Authorization").split("_")[0]] === rreq.get("Authorization").split("_")[1]) {
+
+ fetch(`http://${globalConfig.couchdb.host}/etyd${rreq.path.replace("/etyd", "")}`, {
+ headers: {
+ "Authorization": `Basic ${btoa(globalConfig.couchdb.authorization)}`
+ }
+ }).then(dbRes => {
+
+ if (dbRes.status == 404) {
+ rres.sendStatus(404)
+ } else {
+ dbRes.json().then(dbRes => {
+
+ fetch(`http://${globalConfig.couchdb.host}/etyd${rreq.path.replace("/etyd", "")}`, {
+ method: "DELETE",
+ headers: {
+ "Authorization": `Basic ${btoa(globalConfig.couchdb.authorization)}`,
+ "If-Match": dbRes["_rev"]
+ }
+ }).then(fetchRes => {
+ if (fetchRes.status == 200) {
+ console.log(`${rres.get("cf-connecting-ip")} DELETE ${rreq.path} returned 200 KEY: ${rreq.get("Authorization")}`)
+ rres.sendStatus(200)
+ }
+ }).catch(fetchError => {
+ rres.sendStatus(500)
+ console.log(`${rres.get("cf-connecting-ip")} DELETE ${rreq.path} returned 500: ${fetchError}`)
+ })
+
+ })
+ }
+
+ }).catch(fetchError => {
+ rres.sendStatus(500)
+ console.log(`${rres.get("cf-connecting-ip")} DELETE ${rreq.path} returned 500: ${fetchError}`)
+ })
+
+ } else {
+ console.log(`${rreq.get("cf-connecting-ip")} DELETE ${rreq.path} returned 401`) // log ip of unauthorized requests
+ rres.sendStatus(401) // received auth key was not in database
+ }
+ }
+ }
+ }).catch(fetchError => {
+ rres.sendStatus(500)
+ console.log(`${rres.get("cf-connecting-ip")} DELETE ${rreq.path} returned 500: ${fetchError}`)
+ })
+
+})
+
+
+
module.exports = {app} // export routes to be imported by index for execution
\ No newline at end of file
--
2.49.1
From 2000a2f18d9e5cfb2009dd5f1c1bb51530308ecc Mon Sep 17 00:00:00 2001
From: Enstrayed <48845980+Enstrayed@users.noreply.github.com>
Date: Tue, 23 Apr 2024 08:07:44 -0700
Subject: [PATCH 3/8] etyd Frontend add dark mode support
---
etydFrontend/_static/index.css | 18 ++++++++++++++++++
1 file changed, 18 insertions(+)
diff --git a/etydFrontend/_static/index.css b/etydFrontend/_static/index.css
index cf34de1..66ddd02 100644
--- a/etydFrontend/_static/index.css
+++ b/etydFrontend/_static/index.css
@@ -19,4 +19,22 @@ body {
.resultfeed {
min-height: 20vh;
}
+}
+
+@media (prefers-color-scheme: dark) { /* Dark mode support */
+ body {
+ background-color: black;
+ color: white;
+ }
+
+ input, select, textarea, button {
+ background: none;
+ color: white;
+ border: 2px solid white;
+ }
+
+ input:disabled, button:disabled {
+ opacity: 0.8;
+ cursor: not-allowed;
+ }
}
\ No newline at end of file
--
2.49.1
From 89f2bfecdb0c5cd9ffdabbca54d4e46bfd894651 Mon Sep 17 00:00:00 2001
From: Enstrayed <48845980+Enstrayed@users.noreply.github.com>
Date: Thu, 2 May 2024 17:32:03 -0700
Subject: [PATCH 4/8] working changes
---
routes/etyd.js | 49 +++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 49 insertions(+)
diff --git a/routes/etyd.js b/routes/etyd.js
index 699fd0e..1d8235c 100644
--- a/routes/etyd.js
+++ b/routes/etyd.js
@@ -84,6 +84,55 @@ app.delete("/etyd*", (rreq,rres) => {
})
+// app.post("/etyd*", (rreq,rres) => {
+
+// fetch(`http://${globalConfig.couchdb.host}/apiauthkeys/${globalConfig.etyd.authKeysDoc}`, {
+// headers: {
+// "Authorization": `Basic ${btoa(globalConfig.couchdb.authorization)}`
+// }
+// }).then(dbRes => dbRes.json()).then(dbRes => {
+
+// if (dbRes.status == 404) { // If document containing cider auth keys does not exist
+// console.log(`ERROR: Could not find apiauthkeys/${globalConfig.etyd.authKeysDoc}`)
+// rres.sendStatus(500) // Refuse request
+// } else {
+// if (rreq.get("Authorization") == null) { // If authorization header is not supplied
+// rres.sendStatus(400) // then return bad request (would return 500 otherwise)
+// } else {
+// if (dbRes["content"][rreq.get("Authorization").split("_")[0]] === rreq.get("Authorization").split("_")[1]) {
+
+// fetch(`http://${globalConfig.couchdb.host}/etyd${rreq.path.replace("/etyd", "")}`, {
+// headers: {
+// "Authorization": `Basic ${btoa(globalConfig.couchdb.authorization)}`
+// }
+// }).then(dbRes => {
+
+// if (dbRes.status !== 404) {
+// console.log(`${rres.get("cf-connecting-ip")} POST ${rreq.path} returned 409 KEY: ${rreq.get("Authorization")}`)
+// rres.sendStatus(409)
+// } else {
+
+
+
+// }
+
+// }).catch(fetchError => {
+// rres.sendStatus(500)
+// console.log(`${rres.get("cf-connecting-ip")} DELETE ${rreq.path} returned 500: ${fetchError}`)
+// })
+
+// } else {
+// console.log(`${rreq.get("cf-connecting-ip")} DELETE ${rreq.path} returned 401`) // log ip of unauthorized requests
+// rres.sendStatus(401) // received auth key was not in database
+// }
+// }
+// }
+// }).catch(fetchError => {
+// rres.sendStatus(500)
+// console.log(`${rres.get("cf-connecting-ip")} DELETE ${rreq.path} returned 500: ${fetchError}`)
+// })
+
+// })
module.exports = {app} // export routes to be imported by index for execution
\ No newline at end of file
--
2.49.1
From 2e6b4db4fd2a82d2d37666211aa5fad814c7003b Mon Sep 17 00:00:00 2001
From: Enstrayed <48845980+Enstrayed@users.noreply.github.com>
Date: Wed, 12 Jun 2024 17:43:42 -0700
Subject: [PATCH 5/8] improve blogpost and disable cider
---
routes/blog.js | 27 +++++++--
routes/cider.js | 154 ++++++++++++++++++++++++++----------------------
2 files changed, 104 insertions(+), 77 deletions(-)
diff --git a/routes/blog.js b/routes/blog.js
index c1e6f22..b0415d7 100644
--- a/routes/blog.js
+++ b/routes/blog.js
@@ -7,19 +7,33 @@ app.get("/blogposts", (rreq, rres) => {
if (Date.now() < timeSinceLastQuery+10000) { // if it has been <10 seconds since last request
rres.set("Access-Control-Allow-Origin","*")
- rres.send(cachedResult) // send cached json
+
+ if (rreq.query.format === "html") { // if ?format=html then send HTML
+ rres.send(cachedResult.asHtml)
+ } else { // otherwise send json
+ rres.send(cachedResult.asJson)
+ }
+
} else {
timeSinceLastQuery = Date.now()
cachedResult = parseFiles()
rres.set("Access-Control-Allow-Origin","*")
- rres.send(cachedResult);
+
+ if (rreq.query.format === "html") { // if ?format=html then send HTML
+ rres.send(cachedResult.asHtml)
+ } else { // otherwise send json
+ rres.send(cachedResult.asJson)
+ }
}
})
function parseFiles() {
let files = fs.readdirSync(globalConfig.blog.postsDirectory)
- let parsedFiles = []
+ let result = {
+ asJson: [],
+ asHtml: ""
+ }
for (x in files) {
if (files[x].endsWith(".html") === false) { break } // If file/dir is not .html then ignore
@@ -29,12 +43,13 @@ function parseFiles() {
date = date.replace(/.{2}/g,"$&-").replace("-","").slice(0,-1) // Insert a dash every 2 characters, remove the first dash, remove the last character
- let name = files[x].slice(9).replace(/รท/g," ").replace(".html","") // Strip Date, replace seperator with space & remove file extension
+ let name = files[x].slice(9).replace(/-/g," ").replace(".html","") // Strip Date, replace seperator with space & remove file extension
- parsedFiles.push({ "date": date, "name": name, "path": `${globalConfig.blog.postsDirUrl}/${files[x]}`}) // Add metadata as JSON to array
+ result.asJson.unshift({ "date": date, "name": name, "path": `${globalConfig.blog.postsDirUrl}/${files[x]}`}) // Add to asJson array in the result
+ result.asHtml = `${date} ${name}`+result.asHtml
}
- return parsedFiles.reverse()
+ return result
}
module.exports = {app}
\ No newline at end of file
diff --git a/routes/cider.js b/routes/cider.js
index b309411..22118b6 100644
--- a/routes/cider.js
+++ b/routes/cider.js
@@ -2,87 +2,99 @@ const { app, db, globalConfig } = require("../index.js") // Get globals from ind
var timeSinceLastCiderQuery = Date.now()-2000;
var currentListening = {}
+var currentListeningHtml = ""
-app.get("/cider", (rreq,rres) => { // GET current listening from target
-
- if (Date.now() < timeSinceLastCiderQuery+2000) {
- rres.send(currentListening); // If it has been <2 seconds since the last request, return the cached result.
- } else {
- getCurrentListening(globalConfig.cider.targetHosts[0]).then(funcRes => {
- if (funcRes == 1) {
- rres.sendStatus(503) // If there was a problem getting the upstream JSON, return 503 Service Unavailable.
- } else {
- rres.set("Access-Control-Allow-Origin","*") // Required (I think?) because of CORS.
- currentListening = funcRes
- rres.send(funcRes)
- }
- })
- }
-
+app.get("/cider", (rreq,rres) => {
+ rres.send("Cider endpoint is temporarily unavailable.")
})
+// app.get("/cider", (rreq,rres) => { // GET current listening from target
-app.post("/cider", (rreq,rres) => { // POST stop listening on cider target
+// if (Date.now() < timeSinceLastCiderQuery+2000) {
+// rres.send(currentListening); // If it has been <2 seconds since the last request, return the cached result.
+// } else {
+// getCurrentListening(globalConfig.cider.targetHosts[0],"json").then(funcRes => {
+// if (funcRes == 1) {
+// rres.sendStatus(503) // If there was a problem getting the upstream JSON, return 503 Service Unavailable.
+// } else {
+// rres.set("Access-Control-Allow-Origin","*") // Required (I think?) because of CORS.
+// currentListening = funcRes
+// rres.send(funcRes)
+// }
+// })
+// }
- fetch(`http://${globalConfig.couchdb.host}/apiauthkeys/${globalConfig.cider.authKeysDoc}`, {
- headers: {
- "Authorization": `Basic ${btoa(globalConfig.couchdb.authorization)}`
- }
- }).then(dbRes => dbRes.json()).then(dbRes => {
+// })
- if (dbRes.status == 404) { // If document containing cider auth keys does not exist
- console.log(`ERROR: Could not find apiauthkeys/${globalConfig.mailjet.authKeysDoc}`)
- rres.sendStatus(500) // Refuse request
- } else {
- if (dbRes["content"][rreq.get("Authorization").split("_")[0]] === rreq.get("Authorization").split("_")[1]) {
+// app.post("/cider", (rreq,rres) => { // POST stop listening on cider target
- fetch(`http://${globalConfig.cider.targetHosts[0]}/stop`).then(fres => { // send GET /stop to cider target
- if (fres.status == 204) {
- console.log(`${rreq.get("cf-connecting-ip")} POST /cider returned 200 KEY:${rreq.get("Authorization")}`)
- rres.sendStatus(200) // if that works then 200
- } else {
- rres.sendStatus(500) // otherwise lol
- }
- }).catch(ferror => {
- rres.sendStatus(503) // and if a problem happens its probably cause cider target is unavailable
- })
+// fetch(`http://${globalConfig.couchdb.host}/apiauthkeys/${globalConfig.cider.authKeysDoc}`, {
+// headers: {
+// "Authorization": `Basic ${btoa(globalConfig.couchdb.authorization)}`
+// }
+// }).then(dbRes => dbRes.json()).then(dbRes => {
- } else {
- console.log(`${rreq.get("cf-connecting-ip")} POST /cider returned 401`) // log ip of unauthorized requests
- rres.sendStatus(401) // received auth key was not in database
- }
- }
- })
+// if (dbRes.status == 404) { // If document containing cider auth keys does not exist
+// console.log(`ERROR: Could not find apiauthkeys/${globalConfig.mailjet.authKeysDoc}`)
+// rres.sendStatus(500) // Refuse request
+// } else {
+// if (dbRes["content"][rreq.get("Authorization").split("_")[0]] === rreq.get("Authorization").split("_")[1]) {
-})
+// fetch(`http://${globalConfig.cider.targetHosts[0]}/stop`).then(fres => { // send GET /stop to cider target
+// if (fres.status == 204) {
+// console.log(`${rreq.get("cf-connecting-ip")} POST /cider returned 200 KEY:${rreq.get("Authorization")}`)
+// rres.sendStatus(200) // if that works then 200
+// } else {
+// rres.sendStatus(500) // otherwise lol
+// }
+// }).catch(ferror => {
+// rres.sendStatus(503) // and if a problem happens its probably cause cider target is unavailable
+// })
+
+// } else {
+// console.log(`${rreq.get("cf-connecting-ip")} POST /cider returned 401`) // log ip of unauthorized requests
+// rres.sendStatus(401) // received auth key was not in database
+// }
+// }
+// })
+
+// })
// 2024-04-10: Retrieves currentPlayingSong JSON from specified Cider host and
-// returns JSON containing the useful bits if successful, returning 1 if not.
-async function getCurrentListening(host) { // Host should be hostname/ip & port only.
- timeSinceLastCiderQuery = Date.now(); // Save last time function was run, used to indicate when the cache needs refreshed.
- return await fetch(`http://${host}/currentPlayingSong`).then(fetchRes => {
- if (fetchRes.status == 502) {
- return 1 // If the upstream server returns 502 (Bad Gateway) then internally return 1, indicating error.
- } else {
- return fetchRes.json().then(jsonRes => {
- if (jsonRes.info.name == undefined) {
- return 1 // If Cider is running but not playing a song this check prevents an undefined variable error.
- } else {
- return {
- "songName": jsonRes.info.name,
- "artistName": jsonRes.info.artistName,
- "albumName": jsonRes.info.albumName,
- "songLinkUrl": jsonRes.info.url.songLink,
- "endtimeEpochInMs": jsonRes.info.endTime,
- "artworkUrl": jsonRes.info.artwork.url.replace("{w}", jsonRes.info.artwork.width).replace("{h}", jsonRes.info.artwork.height)
- }
- }
- })
- }
- }).catch(fetchError => {
- console.error("Error fetch()ing upstream Cider host: "+fetchError)
- return 1 // If something else happens then log it and return 1, indicating error.
- })
-}
+// returns JSON/HTML containing the useful bits if successful, returning 1 if not.
+
+// async function getCurrentListening(host,contentType) { // Host should be hostname/ip & port only.
+// timeSinceLastCiderQuery = Date.now(); // Save last time function was run, used to indicate when the cache needs refreshed.
+// return await fetch(`http://${host}/currentPlayingSong`).then(fetchRes => {
+// if (fetchRes.status == 502) {
+// return 1 // If the upstream server returns 502 (Bad Gateway) then internally return 1, indicating error.
+// } else {
+// return fetchRes.json().then(jsonRes => {
+// if (jsonRes.info.name == undefined) {
+// return 1 // If Cider is running but not playing a song this check prevents an undefined variable error.
+// } else {
+// if (contentType === "json") {
+// return {
+// "songName": jsonRes.info.name,
+// "artistName": jsonRes.info.artistName,
+// "albumName": jsonRes.info.albumName,
+// "songLinkUrl": jsonRes.info.url.songLink,
+// "endtimeEpochInMs": jsonRes.info.endTime,
+// "artworkUrl": jsonRes.info.artwork.url.replace("{w}", jsonRes.info.artwork.width).replace("{h}", jsonRes.info.artwork.height)
+// }
+// } else if (contentType === "html") {
+// return `
I'm listening to
${`${jsonRes.info.name} by ${jsonRes.info.artistName}`}