diff --git a/README.md b/README.md
index 778e86c..f113d51 100644
--- a/README.md
+++ b/README.md
@@ -4,7 +4,7 @@ Please don't use this yet, it's not finished
See the software in action: [deadvey.com](https://deadvey.com)
# Confiuration
-Read the [configuation guide](CONFIG.md) for configuration help (in config.json)
+Read the [configuation guide](docs/CONFIG.md) for configuration help (in config.json)
# Features
* post creation via the web frontend (no need to remote to your server to make a post)
@@ -18,23 +18,21 @@ Read the [configuation guide](CONFIG.md) for configuration help (in config.json)
* Commenting on posts
* sign up and delete account
* ejs
+* custom CSS _file_
# Bugs
* probably scales like shit
* probably insecure as hell
# Planned features/todo list
-* custom CSS _file_
-* custom strings use format indicators
-* seperate functions into modules
+* URGENT give each post and user a hard postID to prevent potential issues
+* edit user (could be on instead of the delete_account page)
* user specific RSS feeds
* atom
* federation (looks tricky)
* All strings (including in edit and post page) customisable
* formatable custom strings
-* split code into files to tidy it up a bit
* inline comments and docs
-* give each post a hard postID to prevent potential issues
* clean up code a bit
* comment pages?
diff --git a/app.js b/app.js
deleted file mode 100755
index 4006924..0000000
--- a/app.js
+++ /dev/null
@@ -1,552 +0,0 @@
-// Get the libraries
-const fs = require('fs'); // For modifying and reading files
-const express = require('express'); // For running a webserver in nodejs
-const showdown = require('showdown') // For converting markdown to html on demand, https://showdownjs.com/
-const crypto = require('crypto'); // For encrypting passwords, I use sha512
-// fromUnixTime(): Create a date from a Unix timestamp (in seconds). Decimal values will be discarded.
-// format(): Return the formatted date string in the given format. The result may vary by locale.
-// getUnixTime(): Get the seconds timestamp of the given date.
-// find out more at https://date-fns.org/ \or docs: https://date-fns.org/docs/Getting-Started
-const { fromUnixTime, format, getUnixTime } = require("date-fns") // A date utility library
-const ejs = require("ejs")
-const func = require("./functions.js")
-
-// There's only one possible argument, so we can just check if the user passed that one
-// TODO I plan on adding more such as --help and --post so I should make this more robust at some point
-if (process.argv[2] == "--first-time") {
- initialise() // Creates any files such users.js, posts.js, comments.js or config.js if they are not present
-}
-
-// Define the modules now so they are global
-let users // contains a list of users, each user is an object containing username,prettyname,hash and description
-let posts // contains a list of posts,
-let comments // contains a list of comments
-let config // contains a set of configuration for the site, see example-config.js for an example
-let ejs_templates
-
-try {
- // We're going to try and import the modules,
- users = require('./users.json');
- posts = require('./posts.json');
- comments = require('./comments.json');
- config = require('./config.json');
- ejs_templates = require("./ejs-templates.js")
-}
-catch (error) {
- // if they don't all import then
- // inform the user to pass --first-time and exit with an error code
- console.log("A file is missing!")
- console.log("Run with --first-time to initialise the program")
- console.log(error)
- process.exit(1)
-}
-
-// https://showdownjs.com/docs/available-options
-let converter = new showdown.Converter({
- simpleLineBreaks: true, // Parse line breaks as
in paragraphs (GitHub-style behavior).
- tables: true, // Enable support for tables syntax.
- strikethrough: true, // Enable support for strikethrough: ~~text~~
- tasklists: true, // Enable support for GitHub style tasklists. - [x] and - [ ]
- encodeEmails: true, //Enable automatic obfuscation of email addresses. emails are encoded via character entities
- headerLevelStart: 3, //Set starting level for the heading tags.
-})
-
-// The footer div is globale because it's a site wide, so define it here
-let footer_div = config.site_wide_footer
-footer_div = replace_format_indicators(footer_div)
-
-// Define stuff to do with express (nodejs webserver)
-const app = express();
-app.use(express.urlencoded({ extended: true }));
-app.use(express.json());
-app.use(express.static(config.root_path));
-// set the view engine to ejs
-app.set('view engine', 'ejs');
-
-// Initialise the program by creating users.js, comments.js, posts.js and config.js
-// All require default content in them to start off with
-// Then exit successfully
-// returns nothing
-function initialise() {
- try {
- const users = require("./users.js");
- }
- catch (error) {
- console.log("Creating users file")
- fs.writeFileSync(`${__dirname}/users.json`, `{\n"users": []\n}`)
- }
- try {
- const posts = require("./posts.json");
- }
- catch (error) {
- console.log("Creating posts file")
- fs.writeFileSync(`${__dirname}/posts.json`, `{\n"posts": []\n}`)
- }
- try {
- const comments = require("./comments.json");
- }
- catch (error) {
- console.log("Creating comments file")
- fs.writeFileSync(`${__dirname}/comments.json`, `{\n"comments": [],\n"counter": 0}`)
- }
- try {
- const config = require("./config.js");
- }
- catch (error) {
- console.log("Copying the example config to config.js")
- console.log("!!! PLEASE MODIFY config.js TO YOUR NEEDS !!!")
- fs.copyFile('example-config.js', 'config.js', (err) => {
- console.log("Error copying file")
- })
- }
- console.log("Successfully initialised")
- process.exit(0)
-}
-
-// The users are stored as a list of objects [ user_object, user_object, user_object ]
-// So you cannot easily find the userID (position in list) from the username
-// This function returns the username for a given userID by looping over every user
-// if the user is present, it returns the index of the user (integer)
-// if the user is not present it returns -1
-function get_userID(username) {
- for (let i = 0; i < users.length; i++) { // Loop over every user
- if (users[i]['username'] == username) {
- return i // If the username matches then return the index of that user
- }
- }
- return -1 // If user is not present, return -1
-}
-
-
-// This is similar to the above function, however, instead of formatting to the users
-// configuration, it formats to RFC-822 which is the date format used by RSS feeds
-// eg "Mon, 23 May 2025 18:59:59 +0100"
-// accepts unix time (int)
-// returns the formatted date (string)
-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}`
-}
-
-// This function accepts a list of strings eg ["string1","string2,"string3"] (any length)
-// then returns a string of them each pointing to a seperate url
-// eg "string1, string2, string3"
-// this is so you can have a list of tags that each point to their individual tag page
-// returns: string
-function hyperlink_tags(tags) {
- string = "" // Initialises the string
- for (let tag_index = 0; tag_index < tags.length; tag_index++) { // Loop over each tag
- string += `${tags[tag_index]}` // Adds the tag to the string as a HTML href
- if (tag_index < tags.length - 1) { // If there are more tags, then insert a comma
- string += ", ";
- }
- }
- return string
-}
-
-// See the readme format indicators section for a full list of format indicators
-// This function replaces the format indicators in a template to the content they represent
-// accepts the template (string),
-// the post index (int) as an optional paramter to indicate what post is to be used (for replacing things like content and titles of posts)
-// the tag (strig) as an optional parameter to indicate what tag is being used (for /tag/:tag pages)
-// the user index (int) is an optional parameter to indicate what user is to be used (for replacng things like the header of the user page)
-// returns the template with it's format indiactors replaced (string)
-function replace_format_indicators(template, post_index=-1, tag_name="tag", user_index=-1) {
- output_string = template // These should always be replaceable
- .replaceAll("%%", "%")
- .replaceAll("%J", "/delete_account")
- .replaceAll("%P", "/post")
- .replaceAll("%O", `/edit/${post_index}`)
- .replaceAll("%Q", "/signup")
- .replaceAll("%R", "/rss")
- .replaceAll("%Y", config.site_name)
- .replaceAll("%W", config.site_description)
- .replaceAll("%Z", config.attribution)
- .replaceAll("%S", config.seperator)
- if (post_index >= 0) { // These can only be replaced if a post is specified (by default the post id is -1)
- post_object = posts[post_index] // Defines the post object for easy reference
- output_string = output_string
- .replaceAll("%A", (post_object["tags"]))
- .replaceAll("%B", (hyperlink_tags(post_object["tags"])))
- .replaceAll("%C", converter.makeHtml(post_object["content"]))
- //.replaceAll("%D", unix_time_to_date_format(post_object["pubdate"]))
- //.replaceAll("%E", unix_time_to_date_format(post_object["editdate"]))
- .replaceAll("%F", users[post_object["userID"]]['prettyname'])
- .replaceAll("%G", tag_name)
- .replaceAll("%I", converter.makeHtml(users[post_object['userID']]['description']))
- .replaceAll("%L", `/post/${post_index}`)
- .replaceAll("%M", return_comments(post_index))
- .replaceAll("%N", users[post_object["userID"]]['username'])
- .replaceAll("%S", config.seperator)
- .replaceAll("%T", post_object["title"])
- .replaceAll("%U", `/user/${users[post_object["userID"]]['username']}`)
- .replaceAll("%X", `