From dcd9faa1f9ad49b6ff623a5d5c42eb985e5a80d2 Mon Sep 17 00:00:00 2001 From: deadvey Date: Wed, 9 Jul 2025 17:41:24 +0100 Subject: [PATCH] Version 1.0\nusable, but some stuff still to do --- .gitignore | 5 ++ .posts.js.swp | Bin 0 -> 36864 bytes app.js | 157 ++++++++++++++++++++++++++++++++++++++------------ config.js | 100 ++++++++++++++++++++++++++------ testposts.js | 1 + 5 files changed, 207 insertions(+), 56 deletions(-) create mode 100755 .gitignore create mode 100644 .posts.js.swp mode change 100644 => 100755 app.js mode change 100644 => 100755 config.js create mode 100755 testposts.js diff --git a/.gitignore b/.gitignore new file mode 100755 index 0000000..0ca753a --- /dev/null +++ b/.gitignore @@ -0,0 +1,5 @@ +package.json +node_modules +package-lock.json +posts.js +users.js diff --git a/.posts.js.swp b/.posts.js.swp new file mode 100644 index 0000000000000000000000000000000000000000..1e9bcef00b2871cc8919d4bf99cee67a6a7de41b GIT binary patch literal 36864 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 literal 0 HcmV?d00001 diff --git a/app.js b/app.js old mode 100644 new mode 100755 index 8c07af8..10d13e2 --- a/app.js +++ b/app.js @@ -1,48 +1,111 @@ const express = require('express'); -const crypto = require('crypto'); +const crypto = require('crypto'); // For encrypting passwords +const { fromUnixTime, format, getUnixTime } = require("date-fns") const fs = require('fs'); const users = require('./users.js'); const posts = require('./posts.js'); const config = require('./config.js'); const app = express(); -const port = 8005; +const port = 8080; app.use(express.urlencoded({ extended: true })); app.use(express.json()); app.use(express.static(config.root_path)); -function unix_time_to_date_format(unix_time) { - let date_object = new Date(unix_time) - let formatter = new Intl.DateTimeFormat(config.date_format,config.date_options); - let formatted_time = formatter.format(date_object); - - return formatted_time +function get_userID(username) { + for (let i = 0; i < users.users.length; i++) { + if (users.users[i]['username'] == username) { + return i + } + } + return -1 } -function replace_format_indicators(input_string, post_index) { +function unix_time_to_date_format(unix_time) { + date = fromUnixTime(unix_time) + formatted_date = format(date, config.date_format) + + return formatted_date +} + +function unix_time_to_rss_date(unix_time) { + date = fromUnixTime(unix_time) + formatted_date = format(date, "EEE, dd MMM yyyy HH:mm:ss") + return `${formatted_date} ${config.time_zone}` +} + +function hyperlink_tags(tags) { + string = "" + for (let tag_index = 0; tag_index < tags.length; tag_index++) { + string += `${tags[tag_index]}` + if (tag_index < tags.length - 1) { + string += ", "; + } + } + return string +} + +function replace_format_indicators(input_string, post_index=0, tag_name="tag") { post_object = posts.posts[post_index] output_string = input_string - .replace("%A", (post_object["tags"])) - .replace("%C", post_object["content"]) - .replace("%D", unix_time_to_date_format(post_object["pubdate"])) - .replace("%E", unix_time_to_date_format(post_object["editdate"])) - .replace("%L", `/post/${post_index}`) - .replace("%N", post_object["poster"]) - .replace("%P", "/post") - .replace("%O", "/edit") - .replace("%R", "/rss") - .replace("%S", config.seperator) - .replace("%T", post_object["title"]) - .replace("%U", `/user/${post_object["poster"]}`) - .replace("%Y", config.site_name) - .replace("%W", config.site_description) + .replaceAll("%A", (post_object["tags"])) + .replaceAll("%B", (hyperlink_tags(post_object["tags"]))) + .replaceAll("%C", post_object["content"].replaceAll("\n","
")) + .replaceAll("%D", unix_time_to_date_format(post_object["pubdate"])) + .replaceAll("%E", unix_time_to_date_format(post_object["editdate"])) + .replaceAll("%F", users.users[post_object["userID"]]['prettyname']) + .replaceAll("%G", tag_name) + .replaceAll("%I", users.users[post_object['userID']]['description']) + .replaceAll("%L", `/post/${post_index}`) + .replaceAll("%N", users.users[post_object["userID"]]['username']) + .replaceAll("%P", "/post") + .replaceAll("%O", "/edit") + .replaceAll("%R", "/rss") + .replaceAll("%S", config.seperator) + .replaceAll("%T", post_object["title"]) + .replaceAll("%U", `/user/${users.users[post_object["userID"]]['username']}`) + .replaceAll("%Y", config.site_name) + .replaceAll("%W", config.site_description) return output_string } +app.get(config.rss_path, (req,res) => { + if (config.rss == false) { + res.send("Sorry, RSS is disabled!") + } + else { + let rss_content = ` + + + ${config.site_name} + ${config.site_url} + ${config.site_description} + ` + for (let i = posts.posts.length-1; i >= 0; i--) { + rss_content += ` + + ${posts.posts[i]["title"]} + ${config.site_url}/post/${i}.${config.file_extension} + ")}]]> + ${config.site_url}/post/${i} + ${unix_time_to_rss_date(posts.posts[i]['pubdate'])}` + for (let j = 0; j < posts.posts[i]['tags'].length; j++) { + rss_content += `` + }; + rss_content += "" + } + rss_content += ` + + ` + res.setHeader('content-type', 'application/rss+xml'); + res.send(rss_content) + }; +}); + app.get("/", (req,res) => { header_div = config.timeline_header - header_div = replace_format_indicators(header_div, 0); + header_div = replace_format_indicators(header_div); posts_div = ""; counter = posts.posts.length - 1; while ((counter >= 0) && (counter > (posts.posts.length - (config.timeline_length + 1)))) @@ -51,13 +114,13 @@ app.get("/", (req,res) => { posts_div += replace_format_indicators(post, counter); counter -= 1; } - res.send(`
${posts_div}
`); + res.send(`
${posts_div}
`); }); app.get("/post", (req,res) => { - res.send(`
+ res.send(`
-
+



@@ -69,21 +132,35 @@ app.get("/edit", (req,res) => { }); app.get("/user/:username", (req, res) => { - header_div = `

${req.params.username}

` + header_div = config.user_page_header + header_div = replace_format_indicators(header_div) posts_div = ""; for (let post_index = posts.posts.length-1; post_index >= 0; post_index--) { - if (posts.posts[post_index]["poster"] == req.params.username) { + if (users.users[posts.posts[post_index]["userID"]]["username"] == req.params.username) { let post = config.user_post_format; posts_div += replace_format_indicators(post, post_index); } } - res.send(`
${posts_div}
`); + res.send(`
${posts_div}
`); }); app.get("/post/:post_index", (req, res) => { post_div = ""; let post = config.post_page_format; post_div += replace_format_indicators(post, req.params.post_index); - res.send(`
${post_div}
`); + res.send(`
${post_div}
`); +}); +app.get("/tag/:tag", (req,res) => { + const tag = req.params.tag + let header_div = config.tag_page_header + header_div = replace_format_indicators(header_div,0,tag) + let page_content = "" + for (let i = posts.posts.length-1; i >= 0; i--) { + if (posts.posts[i]['tags'].includes(tag)) { + let post = config.tag_post_format; + page_content += replace_format_indicators(post, i); + }; + }; + res.send(`
${page_content}
`); }); app.post("/submit_post", (req,res) => { @@ -92,19 +169,23 @@ app.post("/submit_post", (req,res) => { const title = req.body.title const content = req.body.content const tags = req.body.tags.split(','); - const datetime = new Date().getTime() + const unix_timestamp = getUnixTime(new Date()) console.log(username, "is submitting a post titled:", title); - if (users.users[username] == password) { // Password matches + if (get_userID(username) == -1) { + res.send("User does not exist") + } + + else if (users.users[get_userID(username)]['hash'] == password) { // Password matches posts.posts.push({ - "poster": username, + "userID": get_userID(username), "title": title, "content": content, - "pubdate": datetime, - "editdate": datetime, + "pubdate": unix_timestamp, + "editdate": unix_timestamp, "tags": tags, }) - fs.writeFileSync(`${config.root_path}/posts.js`, `export const posts = ${JSON.stringify(posts.posts)}`, 'utf-8'); + fs.writeFileSync(`${__dirname}/posts.js`, `export const posts = ${JSON.stringify(posts.posts)}`, 'utf-8'); res.redirect(302, "/"); } else { @@ -113,5 +194,5 @@ app.post("/submit_post", (req,res) => { }); app.listen(port, () => { - console.log(`Server is running at http://localhost:${port}`); + console.log(`Server is running at http://localhost:${port} in ${config.root_path}`); }); diff --git a/config.js b/config.js old mode 100644 new mode 100755 index 7cc5b05..30fe7b2 --- a/config.js +++ b/config.js @@ -1,28 +1,30 @@ export const seperator = "
" -export const site_name = "DeaDvey's Blog" +export const site_name = "Deadvey's Blog" +export const site_url = "https://deadvey.com" export const site_description = "Films, tech, random shit" export const timeline_length = 20 -export const root_path = "/home/gaming/code/web/blogger" +// Anything in this directory will be in the webroot, so put favicon.ico and anything else here. +export const root_path = "/var/www/deadvey.com/blog" -// Date format using https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/toLocaleDateString -export const date_format = 'en-GB'; -export const date_options = { - day: '2-digit', - month: '2-digit', - year: 'numeric', - hour: '2-digit', - minute: '2-digit', - second: '2-digit', - hour12: true, - timeZone: 'UTC' -} +//export const federation = true +//export const fediverse_url = "deadvey.com" +export const rss = true +export const rss_path = "/rss" + +// https://date-fns.org/v4.1.0/docs/format +export const date_format = "yyyy-MM-dd" +export const time_zone = "+0000" //// Format ///// // The syntax for this is pretty simple // %A - List of tags +// %B - List of tags, each one with a hyperlink to that tag page // %C - Post content // %D - Published date in the format specified by date_format // %E - Edited date in the format specified by date_format +// %F - Pretty name +// %G - Tag name (used for the tag page only) +// %I - User description // %L - URL Permanent link to the post // %N - the username of the user (poster) // %P - URL to create a new post @@ -38,17 +40,21 @@ export const timeline_header = `

%Y

%W

Create Post
Edit Post
-RSS Feed +RSS Feed
%S` - +export const user_page_header = `

%F's posts:

+%I +%S` +export const tag_page_header = `

Posts tagged: %G

%S` +// --------------------------------------------- export const user_post_format = `

%T

%C

-%A
+%B
Permalink
%S` export const post_page_format = `

%T

%C

-%A
+%B
By %N
Posted: %D
Edited: %E` @@ -57,3 +63,61 @@ export const timeline_post_format = `

%T

Permalink
By %N %S` +export const tag_post_format = `

%T

+

%C

+%B
+Permalink
+By %N +%S` + + +/// Custom CSS to be applied to every page +export const css = ` +@media (prefers-color-scheme: light) { + body { + background: #ebdbb2; + color: #282828; + } + code { + background: #bdae93; + } + a { + color: #076678; + text-decoration: none; + } + a:visited { + color: #8f3f71; + } + input,textarea,button { + background: #ebdbb2; + color: #282828; + border: 1px solid #282828; + } +} +@media (prefers-color-scheme: dark) { + body { + background: #282828; + color: #ebdbb2; + } + code { + background: #665c54; + box-decoration-break: clone; + display: block; + white-space: pre; + max-width: 50%; + min-width: 100px; + } + a { + color: #83a598; + text-decoration: none; + } + a:visited { + color: #d3869b; + } + input,textarea,button { + background: #282828; + color: #ebdbb2; + border: 1px solid #ebdbb2; + } +} +` diff --git a/testposts.js b/testposts.js new file mode 100755 index 0000000..93e170b --- /dev/null +++ b/testposts.js @@ -0,0 +1 @@ +export const posts = [{"poster":"deadvey","title":"title","content":"content","pubdate":1749292431190,"editdate":1749292431190,"tags":["test","ignore"]},{"poster":"deadvey","title":"post2","content":"awhfjiawfh","pubdate":1749303915416,"editdate":1749303915416,"tags":["test","ignore","hello","goodbye"]},{"poster":"deadvey","title":"test3","content":"afd","pubdate":1750859453223,"editdate":1750859453223,"tags":["test","ignore","hello"]},{"poster":"deadvey","title":"test3","content":"awd","pubdate":1750859714618,"editdate":1750859714618,"tags":["awdwf"]}]