visitor table
This commit is contained in:
parent
6def4fbd98
commit
5ab2b57e79
7
index.js
7
index.js
@ -5,13 +5,14 @@ const serveIndex = require('./src/utils/serve_index')
|
||||
const {engine} = require('express-handlebars')
|
||||
const indexRouter = require('./src/router/indexRouter')
|
||||
const { handlebars } = require('hbs')
|
||||
const bodyParser = require('body-parser')
|
||||
|
||||
const publicPath = "/public"
|
||||
const inUrlPath = "public"
|
||||
|
||||
webserver.engine('.hbs', engine({extname: '.hbs', helpers: {
|
||||
ifDivisibleBy: function (index, divisor, options) {
|
||||
if (index % divisor === 0) {
|
||||
if ((index+1) % divisor === 0) {
|
||||
return options.fn(this);
|
||||
}
|
||||
},
|
||||
@ -27,6 +28,10 @@ webserver.set('view engine', '.hbs');
|
||||
webserver.use(publicPath, express.static(inUrlPath), serveIndex(inUrlPath, {
|
||||
}))
|
||||
|
||||
webserver.use(bodyParser.urlencoded({extend: false}));
|
||||
|
||||
webserver.use(bodyParser.json());
|
||||
|
||||
|
||||
webserver.listen(port, () => {
|
||||
console.log(`Listening on port ${port}`)
|
||||
|
48
package-lock.json
generated
48
package-lock.json
generated
@ -9,13 +9,18 @@
|
||||
"version": "1.0.0",
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"body-parser": "^1.20.3",
|
||||
"byte-size": "^9.0.0",
|
||||
"csv": "^6.3.10",
|
||||
"express": "^4.21.0",
|
||||
"express-handlebars": "^8.0.1",
|
||||
"fs": "^0.0.1-security",
|
||||
"hbs": "^4.2.0",
|
||||
"japanese-date-converter": "^2.0.0",
|
||||
"serve-index": "^1.9.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/node": "^22.10.1"
|
||||
}
|
||||
},
|
||||
"node_modules/@isaacs/cliui": {
|
||||
@ -35,6 +40,16 @@
|
||||
"node": ">=12"
|
||||
}
|
||||
},
|
||||
"node_modules/@types/node": {
|
||||
"version": "22.10.1",
|
||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-22.10.1.tgz",
|
||||
"integrity": "sha512-qKgsUwfHZV2WCWLAnVP1JqnpE6Im6h3Y0+fYgMTasNQ7V++CBX5OT1as0g0f+OyubbFqhf6XVNIsmN4IIhEgGQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"undici-types": "~6.20.0"
|
||||
}
|
||||
},
|
||||
"node_modules/accepts": {
|
||||
"version": "1.3.8",
|
||||
"resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz",
|
||||
@ -200,9 +215,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/cookie": {
|
||||
"version": "0.6.0",
|
||||
"resolved": "https://registry.npmjs.org/cookie/-/cookie-0.6.0.tgz",
|
||||
"integrity": "sha512-U71cyTamuh1CRNCfpGY6to28lxvNwPG4Guz/EVjgf3Jmzv0vlDp1atT9eS5dDjMYHucpHbWns6Lwf3BKz6svdw==",
|
||||
"version": "0.7.1",
|
||||
"resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.1.tgz",
|
||||
"integrity": "sha512-6DnInpx7SJ2AK3+CTUE/ZM0vWTUboZCegxhC2xiIydHR9jNuTAASBrfEpHhiGOZw/nX51bHt6YQl8jsGo4y/0w==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">= 0.6"
|
||||
@ -215,9 +230,9 @@
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/cross-spawn": {
|
||||
"version": "7.0.3",
|
||||
"resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz",
|
||||
"integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==",
|
||||
"version": "7.0.6",
|
||||
"resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz",
|
||||
"integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"path-key": "^3.1.0",
|
||||
@ -370,9 +385,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/express": {
|
||||
"version": "4.21.0",
|
||||
"resolved": "https://registry.npmjs.org/express/-/express-4.21.0.tgz",
|
||||
"integrity": "sha512-VqcNGcj/Id5ZT1LZ/cfihi3ttTn+NJmkli2eZADigjq29qTlWi/hAQ43t/VLPq8+UX06FCEx3ByOYet6ZFblng==",
|
||||
"version": "4.21.1",
|
||||
"resolved": "https://registry.npmjs.org/express/-/express-4.21.1.tgz",
|
||||
"integrity": "sha512-YSFlK1Ee0/GC8QaO91tHcDxJiE/X4FbpAyQWkxAvG6AXCuR65YzK8ua6D9hvi/TzUfZMpc+BwuM1IPw8fmQBiQ==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"accepts": "~1.3.8",
|
||||
@ -380,7 +395,7 @@
|
||||
"body-parser": "1.20.3",
|
||||
"content-disposition": "0.5.4",
|
||||
"content-type": "~1.0.4",
|
||||
"cookie": "0.6.0",
|
||||
"cookie": "0.7.1",
|
||||
"cookie-signature": "1.0.6",
|
||||
"debug": "2.6.9",
|
||||
"depd": "2.0.0",
|
||||
@ -504,6 +519,12 @@
|
||||
"node": ">= 0.6"
|
||||
}
|
||||
},
|
||||
"node_modules/fs": {
|
||||
"version": "0.0.1-security",
|
||||
"resolved": "https://registry.npmjs.org/fs/-/fs-0.0.1-security.tgz",
|
||||
"integrity": "sha512-3XY9e1pP0CVEUCdj5BmfIZxRBTSDycnbqhIOGec9QYtmVH2fbLpj86CFWkrNOkt/Fvty4KZG5lTglL9j/gJ87w==",
|
||||
"license": "ISC"
|
||||
},
|
||||
"node_modules/function-bind": {
|
||||
"version": "1.1.2",
|
||||
"resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz",
|
||||
@ -1352,6 +1373,13 @@
|
||||
"node": ">=0.8.0"
|
||||
}
|
||||
},
|
||||
"node_modules/undici-types": {
|
||||
"version": "6.20.0",
|
||||
"resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.20.0.tgz",
|
||||
"integrity": "sha512-Ny6QZ2Nju20vw1SRHe3d9jVu6gJ+4e3+MMpqu7pqE5HT6WsTSlce++GQmK5UXS8mzV8DSYHrQH+Xrf2jVcuKNg==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/unpipe": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz",
|
||||
|
@ -10,12 +10,17 @@
|
||||
"license": "ISC",
|
||||
"description": "",
|
||||
"dependencies": {
|
||||
"body-parser": "^1.20.3",
|
||||
"byte-size": "^9.0.0",
|
||||
"csv": "^6.3.10",
|
||||
"express": "^4.21.0",
|
||||
"express-handlebars": "^8.0.1",
|
||||
"fs": "^0.0.1-security",
|
||||
"hbs": "^4.2.0",
|
||||
"japanese-date-converter": "^2.0.0",
|
||||
"serve-index": "^1.9.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/node": "^22.10.1"
|
||||
}
|
||||
}
|
||||
|
@ -51,3 +51,8 @@
|
||||
.maotatsu > small::selection{
|
||||
background-color: var(--celeste);
|
||||
}
|
||||
|
||||
.visitor_table > tbody > tr > td{
|
||||
max-width: 160px;
|
||||
overflow-x: scroll;
|
||||
}
|
17
src/router/common_path_logic/home.js
Normal file
17
src/router/common_path_logic/home.js
Normal file
@ -0,0 +1,17 @@
|
||||
const { readCsv } = require("../../utils/csv")
|
||||
const { dirname } = require('path');
|
||||
const rootDir = dirname(require.main.filename);
|
||||
|
||||
module.exports = async (req, res) => {
|
||||
try{
|
||||
const commentsRead = (await readCsv(rootDir + '/public/dynamic/sync/comments.csv'))
|
||||
const comments = commentsRead.slice(commentsRead.length-16, commentsRead.length).reverse()
|
||||
return {
|
||||
comments
|
||||
}
|
||||
}
|
||||
catch(err){
|
||||
console.error(err)
|
||||
res.send("Mistakes were made")
|
||||
}
|
||||
}
|
@ -3,7 +3,7 @@ const express = require('express');
|
||||
const router = express.Router();
|
||||
const { readCsv } = require('../utils/csv');
|
||||
const { dirname } = require('path');
|
||||
const appDir = dirname(require.main.filename);
|
||||
const thisDirectory = dirname(require.main.filename);
|
||||
const fs = require('fs')
|
||||
|
||||
function addPaths(path, renderParams = {}){
|
||||
@ -15,17 +15,17 @@ function addPaths(path, renderParams = {}){
|
||||
const possibleHeader = 'headers/' + viewsRelativeDir.slice(0, -1) + '.hbs'
|
||||
const possibleSettingsPath = '/src/router/common_path_settings/' + viewsRelativeDir.slice(0, -1)
|
||||
|
||||
if (fs.existsSync(appDir + possibleThemeStyle)){
|
||||
if (fs.existsSync(thisDirectory + possibleThemeStyle)){
|
||||
currentDefaultParams.theme = possibleThemeStyle
|
||||
}
|
||||
if (fs.existsSync(appDir + possibleHeaderStyle)){
|
||||
if (fs.existsSync(thisDirectory + possibleHeaderStyle)){
|
||||
currentDefaultParams.header_style = possibleHeaderStyle
|
||||
}
|
||||
if (fs.existsSync(appDir + '/views/partials/' + possibleHeader)){
|
||||
if (fs.existsSync(thisDirectory + '/views/partials/' + possibleHeader)){
|
||||
currentDefaultParams.headerPartial = possibleHeader.slice(0, -4)
|
||||
}
|
||||
if (fs.existsSync(appDir + possibleSettingsPath + '/general.json')){
|
||||
const fileGeneralParams = JSON.parse(fs.readFileSync(appDir + possibleSettingsPath + '/general.json'))
|
||||
if (fs.existsSync(thisDirectory + possibleSettingsPath + '/general.json')){
|
||||
const fileGeneralParams = JSON.parse(fs.readFileSync(thisDirectory + possibleSettingsPath + '/general.json'))
|
||||
currentDefaultParams = {
|
||||
...currentDefaultParams,
|
||||
...fileGeneralParams
|
||||
@ -53,7 +53,42 @@ router.get('/', (_req, res) => {
|
||||
res.redirect('/public/pages/neocities-lyricaltokarev/index.html')
|
||||
})
|
||||
|
||||
addPaths(appDir + '/views/')
|
||||
|
||||
const recent_posters = []
|
||||
|
||||
router.post('/comment', (req, res) => {
|
||||
const ip = req.header('x-forwarded-for') || req.connection.remoteAddress;
|
||||
if(recent_posters.some( poster => poster.ip === ip)){
|
||||
console.log("spammer, " + ip)
|
||||
return res.redirect('/home#visitor_table')
|
||||
}
|
||||
recent_posters.push({
|
||||
ip,
|
||||
timeout: 3600
|
||||
})
|
||||
const comment = req.body.comment.replace(/"/g, '""');
|
||||
fs.appendFileSync(thisDirectory + "/public/dynamic/sync/comments.csv", `\n${Date.now()},"${comment}",,1`)
|
||||
|
||||
res.redirect('/home#visitor_table')
|
||||
})
|
||||
|
||||
|
||||
setInterval(() => {
|
||||
recent_posters.forEach(poster => {
|
||||
poster.timeout -= 1
|
||||
if (poster.timeout <= 0){
|
||||
recent_posters.filter(p => {
|
||||
return poster.ip !== p.ip
|
||||
})
|
||||
}
|
||||
})
|
||||
}, 1000)
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
addPaths(thisDirectory + '/views/')
|
||||
|
||||
|
||||
module.exports = router;
|
@ -18,7 +18,6 @@
|
||||
<li class="red"><strong>Content</strong></li>
|
||||
<li class="red">Audience</li>
|
||||
<li class="red"><strong>Consume</strong></li>
|
||||
<li class="red"><strong>Identity</strong></li>
|
||||
<li>Policy</li>
|
||||
<li>Term</li>
|
||||
<li>Deserve</li>
|
||||
@ -34,9 +33,9 @@
|
||||
<li class="red">Browse</li>
|
||||
<li class="red"><strong>Develop</strong></li>
|
||||
<li class="red">Saturated</li>
|
||||
<li class="red"><strong>Bullying</strong></li>
|
||||
<li>Right</li>
|
||||
<li>Life</li>
|
||||
<li class="red">Life</li>
|
||||
<li class="red">Tweet</li>
|
||||
<li>Obscure</li>
|
||||
<li>Vibe</li>
|
||||
<li>Aesthetic</li>
|
||||
@ -51,6 +50,7 @@
|
||||
<li class="red">Yikes</li>
|
||||
<li class="red">Project</li>
|
||||
<li>Idea</li>
|
||||
<li class="red"><strong>Identity</strong></li>
|
||||
<li class="red">Global</li>
|
||||
<li class="red">Emotional</li>
|
||||
<li>Planning</li>
|
||||
@ -72,6 +72,7 @@
|
||||
<li class="red">Resource</li>
|
||||
<li>Inequality</li>
|
||||
<li>Fee</li>
|
||||
<li class="red"><strong>Bullying</strong></li>
|
||||
<li>Equality</li>
|
||||
<li class="red">System</li>
|
||||
<li>Design</li>
|
||||
@ -90,6 +91,7 @@
|
||||
<li class="red"><strong>Medium</strong></li>
|
||||
<li>Amount</li>
|
||||
<li class="red">Reader</li>
|
||||
<li class="red">Dynamics</li>
|
||||
<li class="red"><strong>Collective</strong></li>
|
||||
<li>Rational</li>
|
||||
<li class="red">Mental</li>
|
||||
@ -107,6 +109,8 @@
|
||||
<li class="red">Activism</li>
|
||||
<li class="red"><strong>Activist</strong></li>
|
||||
<li class="red">Privacy</li>
|
||||
<li class="red"><strong>Cancel</strong></li>
|
||||
<li class="red">Controversial</li>
|
||||
<li>Subscribers</li>
|
||||
<li>Likes</li>
|
||||
<li class="red">Material</li>
|
||||
@ -143,6 +147,7 @@
|
||||
<li><a href="#comicchat">Comic Chat</a></li>
|
||||
<li><a href="#yuugenmagan">YuugenMagan</a></li>
|
||||
<li><a href="#propaganda">Propaganda</a></li>
|
||||
<li><a href="#visitor_table">Visitor Table</a></li>
|
||||
<li><a href="#bottom">???</a></li>
|
||||
</ul>
|
||||
</td>
|
||||
@ -262,7 +267,6 @@
|
||||
<h2 id="yuugenmagan">YuugenMagan</h2>
|
||||
<img title="YuugenMagan" alt="YuugenMagan" src="/public/images/yuugenmagan.png">
|
||||
<p>YuugenMagan</p>
|
||||
|
||||
<hr>
|
||||
<p>
|
||||
<h2 id="propaganda">Propaganda</h2>
|
||||
@ -286,10 +290,39 @@
|
||||
<p>This site is an ip logger. Do not hotlink.</p>
|
||||
</p>
|
||||
|
||||
<hr>
|
||||
|
||||
<h2 id="visitor_table">Visitor Table</h2>
|
||||
<p>Experimental.</p>
|
||||
<table width="100%" class="visitor_table" cellpadding="10" border="1">
|
||||
<tbody>
|
||||
<tr>
|
||||
{{#each comments}}
|
||||
<td valign="top">
|
||||
{{{this.comment}}}
|
||||
</td>
|
||||
{{#ifDivisibleBy @index 4}}
|
||||
</tr>
|
||||
<tr>
|
||||
{{/ifDivisibleBy}}
|
||||
{{/each}}
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<br>
|
||||
<div>
|
||||
<form id="comment_form" method="post" action="/comment">
|
||||
<textarea name="comment"></textarea>
|
||||
<br>
|
||||
<button type="submit">Submit</button>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<hr>
|
||||
|
||||
<audio controls>
|
||||
<source src="https://mfiles.lyricaltokarev.com/1998%20-%20Shin%20Getter%20Robo%20-%20Sekai%20Saigo%20no%20Hi%20-%20Original%20Soundtrack%20Vol.%202/Shin%20Getter%20Robo%20-%20Vol.%202%20-%2022.%20HURRY%20UP%20DREAM%20%EF%BD%9ETabidachi%EF%BD%9E%20%28New%20Ending%20Theme%29.flac" type="audio/mpeg">
|
||||
</audio><br>
|
||||
<hr>
|
||||
{{>lyrics lyrics="<p>
|
||||
熱くなれ夢みた明日を<br>
|
||||
必ずいつかつかまえる<br>
|
||||
|
@ -2,6 +2,7 @@
|
||||
<main>
|
||||
<h2>2024</h2>
|
||||
<ul>
|
||||
<li>5/12 <a href="/home#visitor_table">This has to be a good idea...</a></li>
|
||||
<li>4/12 <a href="/home">Lyrical Tokarev is now under martial rule!</a></li>
|
||||
<li>29/11 <a href="/home#navigation">Added a Navigation section.</a></li>
|
||||
<li>27/11 <a href="/home#bottom">Did you see that shadow?</a></li>
|
||||
|
Loading…
Reference in New Issue
Block a user