diff --git a/build.py b/build.py index ed09915..3737556 100644 --- a/build.py +++ b/build.py @@ -3,6 +3,7 @@ import markdown import re from jinja2 import Environment, FileSystemLoader import yaml +import time import json class Website: @@ -14,7 +15,7 @@ class Website: self.pages = [] self.tags = [] self.all_images = [] - self.about_meta, self.about_content = self.fetch_page('content', 'about.md') + self.about_meta, self.about_content, self.about_modified_time = self.fetch_page('content', 'about.md') def build(self): self.fetch_pages() @@ -30,6 +31,8 @@ class Website: if page.endswith('.md'): with open(os.path.join('content/posts', page), 'r', encoding="utf8") as f: content = f.read() + file_desc = f.fileno() + file_status = os.fstat(file_desc) parts = content.split('---') metadata = yaml.safe_load(parts[1]) md_content = ''.join(parts[2:]) @@ -37,7 +40,7 @@ class Website: md_content = self.format_content(md_content) html_content = markdown.markdown(md_content) output_filename = os.path.splitext(page)[0] + '.html' - new_page = Page(metadata, html_content, output_filename) + new_page = Page(metadata, html_content, output_filename, file_status) self.pages.append(new_page) def process_page(self): @@ -55,6 +58,7 @@ class Website: image=metadata.get('image', ''), # Assuming image is a string showcase=metadata.get('showcase', []), credits=metadata.get('credits', []), # Assuming credits is a string + modified_time=page.get_modified_time_readable(), content=html_content) with open(os.path.join(self.output_dir_root, filename), 'w', encoding='utf8') as output_file: output_file.write(html_output) @@ -73,7 +77,8 @@ class Website: md_content = ''.join(parts[2:]) md_content = re.sub(r'\(([^)]+)\)\[([^\]]+)\]', r'\1', md_content) html_content = markdown.markdown(md_content) - return metadata, html_content + about_modified_time = time.ctime(os.fstat(f.fileno()).st_mtime) + return metadata, html_content, about_modified_time def create_list(self): template = self.env.get_template('list.html') @@ -96,7 +101,8 @@ class Website: template = self.env.get_template('about.html') html_output = template.render( content=self.about_content, - socials=self.about_meta + socials=self.about_meta, + modified_time = self.about_modified_time ) with open(os.path.join('public', 'about.html'), 'w', encoding='utf8') as output_file: output_file.write(html_output) @@ -138,12 +144,13 @@ class Website: with open(json_file, 'w', encoding='utf8') as f: json.dump(page_info_list, f, ensure_ascii=False, indent=4) - + class Page: - def __init__(self, metadata, md_content, filename): + def __init__(self, metadata, md_content, filename, last_updated): self.metadata = metadata self.content = md_content self.filename = filename + self.last_updated = last_updated self.title = self.metadata['title'] self.type = self.metadata['type'] self.year = self.metadata['year'] @@ -185,6 +192,13 @@ class Page: def display_metadata(self): output = f"Title: {self.title}\nYear: {self.year}\nDate: {self.date}\nTags: {self.tags}\nType: {self.type}" print(output) + + def get_modified_time_readable(self): + if self.last_updated is not None: + last_modified_time = self.last_updated.st_mtime + last_modified_time_readable = time.ctime(last_modified_time) + return last_modified_time_readable + return None def main(): inst = Website('templates', 'public') diff --git a/public/about.html b/public/about.html index 428acaa..b920b6a 100644 --- a/public/about.html +++ b/public/about.html @@ -38,6 +38,15 @@
git
+
+

Wanderers:

+

+
+ +
+

Last Modified:

+

Thu Jun 20 17:36:45 2024

+
@@ -48,6 +57,7 @@ + diff --git a/public/articles/(o)machine.html b/public/articles/(o)machine.html index 4df929a..7a6cb39 100644 --- a/public/articles/(o)machine.html +++ b/public/articles/(o)machine.html @@ -47,7 +47,7 @@
-

(2026)

+

(2022)

Speak It Now Eat It, Revision Performing Arts Festival,

Belfast

@@ -73,9 +73,12 @@ -
- -
+ +
+

Last Modified:

+

Fri Jun 21 09:27:25 2024

+
+
diff --git a/public/articles/ai-x-body.html b/public/articles/ai-x-body.html index cf08c45..8f47ecb 100644 --- a/public/articles/ai-x-body.html +++ b/public/articles/ai-x-body.html @@ -46,9 +46,12 @@ -
- -
+ +
+

Last Modified:

+

Thu Jun 20 17:23:18 2024

+
+ diff --git a/public/articles/beauty-and-the-beep.html b/public/articles/beauty-and-the-beep.html index 8f472df..3302b58 100644 --- a/public/articles/beauty-and-the-beep.html +++ b/public/articles/beauty-and-the-beep.html @@ -88,9 +88,12 @@ -
- -
+ +
+

Last Modified:

+

Sat Jun 8 22:14:44 2024

+
+ diff --git a/public/articles/data.html b/public/articles/data.html index c94ddb2..1b31b84 100644 --- a/public/articles/data.html +++ b/public/articles/data.html @@ -86,9 +86,12 @@ -
- -
+ +
+

Last Modified:

+

Sat Jun 8 23:33:47 2024

+
+ diff --git a/public/articles/demo.html b/public/articles/demo.html index e73e66b..5d33340 100644 --- a/public/articles/demo.html +++ b/public/articles/demo.html @@ -87,9 +87,12 @@ -
- -
+ +
+

Last Modified:

+

Thu Jun 20 18:00:30 2024

+
+ diff --git a/public/articles/dwelling.html b/public/articles/dwelling.html index be7e3fb..a1d4ead 100644 --- a/public/articles/dwelling.html +++ b/public/articles/dwelling.html @@ -79,9 +79,12 @@ -
- -
+ +
+

Last Modified:

+

Sat Jun 8 23:36:42 2024

+
+ diff --git a/public/articles/electronic-image.html b/public/articles/electronic-image.html index 51a69bd..865857d 100644 --- a/public/articles/electronic-image.html +++ b/public/articles/electronic-image.html @@ -82,9 +82,12 @@ -
- -
+ +
+

Last Modified:

+

Sun Jun 9 00:02:18 2024

+
+ diff --git a/public/articles/latent-mirror.html b/public/articles/latent-mirror.html index bf53311..c3f63c0 100644 --- a/public/articles/latent-mirror.html +++ b/public/articles/latent-mirror.html @@ -82,9 +82,12 @@ -
- -
+ +
+

Last Modified:

+

Sat Jun 8 23:39:31 2024

+
+ diff --git a/public/articles/undefined.html b/public/articles/undefined.html index 16ce912..678d6ff 100644 --- a/public/articles/undefined.html +++ b/public/articles/undefined.html @@ -79,9 +79,12 @@ -
- -
+ +
+

Last Modified:

+

Sat Jun 8 23:41:06 2024

+
+ diff --git a/public/css/styles.css b/public/css/styles.css index 21af17f..6264bd1 100644 --- a/public/css/styles.css +++ b/public/css/styles.css @@ -476,6 +476,42 @@ body { margin: 0; } + #modified-time { + display: flex; + flex-direction: row; + flex-wrap: wrap; + gap: 10px; + margin-top: 25px; + } + + #modified-time p{ + padding: 0; + margin: 0; + } + + #modified-time h4{ + padding: 0; + margin: 0; + } + + #wanderers-container { + display: flex; + flex-direction: row; + flex-wrap: wrap; + gap: 10px; + margin-top: 25px; + } + + #wanderers-container p{ + padding: 0; + margin: 0; + } + + #wanderers-container h4{ + padding: 0; + margin: 0; + } + diff --git a/public/js/wander.js b/public/js/wander.js new file mode 100644 index 0000000..7861b53 --- /dev/null +++ b/public/js/wander.js @@ -0,0 +1,9 @@ +function GetWanderCount(){ + let element = document.getElementById('wander-count') + + fetch('../json/counter.json') + .then((response) => response.json()) + .then((json) => element.innerHTML = json['count']); +} + +GetWanderCount() \ No newline at end of file diff --git a/server.js b/server.js index 7dea951..3ef1bb5 100644 --- a/server.js +++ b/server.js @@ -1,6 +1,6 @@ const express = require('express'); const path = require('path'); -const fs = require('fs') +const fs = require('fs'); const bodyParser = require('body-parser'); const crypto = require('crypto'); const { exec } = require('child_process'); @@ -8,37 +8,38 @@ require('dotenv').config(); const app = express(); const PORT = process.env.PORT || 3000; -const GITEA_SECRET = process.env.GITEA_SECRET +const GITEA_SECRET = process.env.GITEA_SECRET; const counterFilePath = path.join(__dirname, 'public/json/counter.json'); function readCounter() { - const data = fs.readFileSync(counterFilePath) - return JSON.parse(data).count; + const data = fs.readFileSync(counterFilePath); + return JSON.parse(data).count; } function writeCounter(count) { - const data = JSON.stringify({ count: count}, null, 2) - fs.writeFileSync(counterFilePath, data) + const data = JSON.stringify({ count: count }, null, 2); + fs.writeFileSync(counterFilePath, data); } -// Serve static files from the 'public' directory -app.use(express.static(path.join(__dirname, 'public'))); +function IncrementCounter() { + let count = readCounter(); + count++; + writeCounter(count); + console.log(count); +} // Middleware to capture raw body app.use(bodyParser.json({ - verify: (req, res, buf, encoding) => { - req.rawBody = buf.toString(encoding || 'utf8'); - } + verify: (req, res, buf, encoding) => { + req.rawBody = buf.toString(encoding || 'utf8'); + } })); + // Custom middleware to handle URLs without .html for specific routes app.use((req, res, next) => { const urlPath = req.path.split('?')[0]; const htmlRoutes = ['/about', '/list', '/gallery']; - let count = readCounter() - count++; - writeCounter(count) - console.log(count) if (htmlRoutes.includes(urlPath)) { req.url += '.html'; } @@ -48,60 +49,65 @@ app.use((req, res, next) => { // Route to serve the index.html file app.get('/', (req, res) => { + IncrementCounter() res.sendFile(path.join(__dirname, 'public', 'index.html')); }); // Routes to serve the HTML files without .html extension app.get('/about.html', (req, res) => { + IncrementCounter(); res.sendFile(path.join(__dirname, 'public', 'about.html')); }); app.get('/list.html', (req, res) => { + IncrementCounter(); res.sendFile(path.join(__dirname, 'public', 'list.html')); }); app.get('/gallery.html', (req, res) => { + IncrementCounter(); res.sendFile(path.join(__dirname, 'public', 'gallery.html')); }); // Serve articles without .html extension app.get('/articles/:articleName', (req, res) => { const articleName = req.params.articleName; + IncrementCounter(); res.sendFile(path.join(__dirname, 'public/articles', `${articleName}.html`)); }); // Webhook handler app.post('/api', (req, res) => { - const signature = req.headers['x-gitea-signature']; - const payload = req.rawBody; - - if (!signature || !payload) { - return res.status(400).send('Invalid payload or missing signature'); - } - - // Verify the secret - const hmac = crypto.createHmac('sha256', GITEA_SECRET); - const digest = hmac.update(payload).digest('hex'); - const bufferSignature = Buffer.from(signature, 'hex'); - const bufferDigest = Buffer.from(digest, 'hex'); - - console.log(bufferSignature.length, bufferDigest.length) - - if (bufferSignature.length === bufferDigest.length && crypto.timingSafeEqual(bufferSignature, bufferDigest)) { - // Secret is valid, update the repository - res.status(200).send('Repository updated successfully'); - // Optionally, execute a shell command to pull the latest changes - exec('git pull', (error, stdout, stderr) => { - if (error) { - console.error(`exec error: ${error}`); - return; - } - console.log(`stdout: ${stdout}`); - console.error(`stderr: ${stderr}`); - }); - } else { - res.status(401).send('Invalid secret'); - } + const signature = req.headers['x-gitea-signature']; + const payload = req.rawBody; + + if (!signature || !payload) { + return res.status(400).send('Invalid payload or missing signature'); + } + + // Verify the secret + const hmac = crypto.createHmac('sha256', GITEA_SECRET); + const digest = hmac.update(payload).digest('hex'); + const bufferSignature = Buffer.from(signature, 'hex'); + const bufferDigest = Buffer.from(digest, 'hex'); + + console.log(bufferSignature.length, bufferDigest.length); + + if (bufferSignature.length === bufferDigest.length && crypto.timingSafeEqual(bufferSignature, bufferDigest)) { + // Secret is valid, update the repository + res.status(200).send('Repository updated successfully'); + // Optionally, execute a shell command to pull the latest changes + exec('git pull', (error, stdout, stderr) => { + if (error) { + console.error(`exec error: ${error}`); + return; + } + console.log(`stdout: ${stdout}`); + console.error(`stderr: ${stderr}`); + }); + } else { + res.status(401).send('Invalid secret'); + } }); // Error handling @@ -110,6 +116,9 @@ app.use((err, req, res, next) => { res.status(500).send('Something broke!'); }); +// Serve static files from the 'public' directory +app.use(express.static(path.join(__dirname, 'public'))); + // Start the server app.listen(PORT, (err) => { if (err) { diff --git a/templates/_modified.html b/templates/_modified.html new file mode 100644 index 0000000..792c50d --- /dev/null +++ b/templates/_modified.html @@ -0,0 +1,5 @@ + +
+

Last Modified:

+

{{ modified_time }}

+
diff --git a/templates/_wanderers.html b/templates/_wanderers.html new file mode 100644 index 0000000..b00b6a9 --- /dev/null +++ b/templates/_wanderers.html @@ -0,0 +1,4 @@ +
+

Wanderers:

+

+
diff --git a/templates/about.html b/templates/about.html index c44f24b..2a3231f 100644 --- a/templates/about.html +++ b/templates/about.html @@ -13,6 +13,8 @@
{{ key }}
{% endfor %} + {% include '_wanderers.html' %} + {% include '_modified.html' %} @@ -23,4 +25,5 @@ + {% endblock %} \ No newline at end of file diff --git a/templates/article.html b/templates/article.html index fadb650..6401a81 100644 --- a/templates/article.html +++ b/templates/article.html @@ -57,9 +57,8 @@ {% endif %} -
- -
+ {% include '_modified.html' %} + {% endblock %}