diff --git a/src/lib/components/Header.svelte b/src/lib/components/Header.svelte new file mode 100644 index 0000000..5819f37 --- /dev/null +++ b/src/lib/components/Header.svelte @@ -0,0 +1,58 @@ + + + + + \ No newline at end of file diff --git a/src/lib/components/Image.svelte b/src/lib/components/Image.svelte deleted file mode 100644 index e69de29..0000000 diff --git a/src/lib/components/PostList.svelte b/src/lib/components/PostList.svelte new file mode 100644 index 0000000..a060303 --- /dev/null +++ b/src/lib/components/PostList.svelte @@ -0,0 +1,25 @@ + + +{#if data && data.postJson && data.postJson.data} + {#each data.postJson.data as post} + + {/each} +{/if} + +

+ + +

\ No newline at end of file diff --git a/src/lib/db/db.js b/src/lib/db/db.js index c1d4c83..fbfb189 100644 --- a/src/lib/db/db.js +++ b/src/lib/db/db.js @@ -1,4 +1,4 @@ -const rowCount = 5; +const ROW_COUNT = 5; const AUTH_ACTIONS = [ 'postCreate', @@ -7,7 +7,9 @@ const AUTH_ACTIONS = [ 'postDelete' ]; -const fileSizeLimit = 1024*1024*16; +const FILE_SIZE_LIMIT = 1024*1024*16; + +const VALID_EXTENSIONS = ['png','jpg','jpeg','gif','svg'] var ridArray = {}; @@ -15,8 +17,8 @@ import sqlite3 from 'sqlite3' import { open } from 'sqlite' import { hash, compare } from 'bcrypt' import { randomBytes, createHash } from 'node:crypto'; -import { readFile, writeFile } from 'node:fs/promises'; -import { calcVote, calcVoteUser, checkLength, checkRegex } from '../util.js'; +import { writeFile } from 'node:fs/promises'; +import { calcVote, checkLength, checkRegex, safePath } from '../util.js'; var db; async function initDb() { @@ -55,8 +57,6 @@ let updateUser = async ({user}) => { let upvotes = 0; let downvotes = 0; - let reputation = 0; - allPosts.forEach(post => { upvotes += post.upvotes || 0; downvotes += post.downvotes || 0; @@ -72,7 +72,7 @@ let updateUser = async ({user}) => { 0, upvotes, downvotes, - calcVoteUser(upvotes,downvotes) + calcVote(upvotes,downvotes,'user') ]); } @@ -169,21 +169,6 @@ backend.postDelete = async ({id, user}) => { return {'success': 'Your post has been deleted!', 'href': `/post/${id}` }; } - -backend.postGet = async ({id, cookies }) => { - var posts = await db.all('SELECT * from post WHERE id = ?', [ - id - ]) - - if (!posts || posts.length < 1) { - return {'success': 'Post does not exist.'} - } - - var user = (await backend.token({cookies})).data; - - return {data: posts[0], isAuthor: posts[0].username == user}; -} - backend.userGet = async ({user}) => { var posts = await db.all('SELECT * from user WHERE username = ?', [ user @@ -208,26 +193,36 @@ backend.userBio = async ({user}) => { return {data: posts[0]}; } -backend.postBulk = async ({page,user}) => { +backend.postBulk = async ({page, id, user, cookies}) => { var posts; - if (!user) { + var userAuth = (await backend.token({cookies})).data; + + if (!user && !id) { posts = await db.all('SELECT * from post ORDER BY rating DESC LIMIT ?, ?', [ - page*rowCount, - rowCount + page*ROW_COUNT, + ROW_COUNT + ]) + } else if (id) { + posts = await db.all('SELECT * from post WHERE id = ?', [ + id ]) } else { posts = await db.all('SELECT * from post WHERE username = ? ORDER BY rating DESC LIMIT ?, ?', [ user, - page*rowCount, - rowCount + page*ROW_COUNT, + ROW_COUNT ]) } + posts = posts.map(post => { + return {...post, isAuthor: userAuth == post.username}; + }) + return {data: posts}; } -backend.vote = async ({cookies, id, vote, user}) => { +backend.vote = async ({id, vote, user}) => { if (!id || (vote != 'down' && vote != 'up')) return {success: 'fail' }; await db.run('DELETE FROM vote WHERE username = ? AND id = ?', [ @@ -300,12 +295,12 @@ backend.fileCreate = async({img, extension,id, last }) => { if (!imgHash) return {'success': 'Image not provided.'} - if (imgHash.length > fileSizeLimit) + if (imgHash.length > FILE_SIZE_LIMIT) return {'success': 'Image too big.'} - const extensionSafe = extension.replace(/[^a-zA-Z]+/g, '\\$1'); + const extensionSafe = safePath(extension); - if (extensionSafe != 'png' && extensionSafe != 'jpg' && extensionSafe != 'svg' && extensionSafe != 'gif') + if (VALID_EXTENSIONS.indexOf(extensionSafe) == -1) return { success: 'Illegal file extension.' }; writeFile(`${process.cwd()}/db/post-${imgHash}.${extensionSafe}`,imgData,{encoding: 'base64'}); diff --git a/src/lib/util.js b/src/lib/util.js index 1858365..167e110 100644 --- a/src/lib/util.js +++ b/src/lib/util.js @@ -20,7 +20,7 @@ let checkRegex = function(string, field, regex) { return false; } -let calcVote = function(up,down) { +let calcVote = function(up,down, type) { var upPadded = up + 3; var downPadded = down + 3; var totalPadded = Math.max(up + down, 3); @@ -28,26 +28,20 @@ let calcVote = function(up,down) { var rating = -Math.log((1 / ((((upPadded - downPadded) / (upPadded + downPadded)) + 1) / 2)) - 1) / Math.log(Math.E); rating = Math.min(rating,10); - rating = Math.max(rating,-1); - rating = (rating + 11) / 1.1; + if (type != 'user') { + rating = Math.max(rating,-1); + + rating = (rating + 11) / 1.1; + + rating = rating * Math.log(totalPadded); + } else { + rating = Math.round(rating * Math.log(totalPadded) * 10); + } return rating * Math.log(totalPadded); } -let calcVoteUser = function(up,down) { - var upPadded = up + 3; - var downPadded = down + 3; - var totalPadded = Math.max(up + down, 3); - - var rating = -Math.log((1 / ((((upPadded - downPadded) / (upPadded + downPadded)) + 1) / 2)) - 1) / Math.log(Math.E); - - rating = Math.min(rating,10); - rating = Math.max(rating,-10); - - return Math.round(rating * Math.log(totalPadded) * 10); -} - let handleSubmit = async e => { const ACTION_URL = e.target.action @@ -59,6 +53,10 @@ let handleSubmit = async e => { }).then(x => x.text()); } +let safeName = function (text) { + return text.replaceAll(/[^A-Za-z0-9\-\_]/g, ''); +} + let formatPost = function(post) { post = post.split('\n'); @@ -69,29 +67,26 @@ let formatPost = function(post) { post = post.map(line => { line = line.map(subPost => { var splitPost = subPost.split('||'); + if (splitPost.length > 1) { var cap1 = splitPost[0]; if (cap1 == 'img') { - var matchCleaned = splitPost[1].replace(/(\s+)/g, '\\$1'); + var matchCleaned = safeName(subPost[1]); splitPost = {'type': 'img', 'url': `/img/${matchCleaned}`}; return splitPost; } - } else if (subPost[0] == '@') { - var subPostIn = subPost.substring(0).replaceAll(/[^A-Za-z0-9\-\_]/g, ''); + } else if (subPost[0] == '@' || subPost[0] == '#') { + var subPostIn = safeName(subPost.substring(0)); - splitPost = {'type': 'link', 'display': subPost, 'url': `/user/${subPostIn}`}; + var type = (subPost[0] == '@') ? 'user' : 'post'; + + splitPost = {'type': 'link', 'display': subPost, 'url': `/${type}/${subPostIn}`}; return splitPost; - } else if (subPost[0] == '#') { - var subPostIn = subPost.substring(0).replaceAll(/[^A-Za-z0-9]/g, ''); - - splitPost = {'type': 'link', 'display': subPost, 'url': `/post/${subPostIn}`}; - - return splitPost; } return subPost; @@ -102,16 +97,20 @@ let formatPost = function(post) { return post; } -function block(bool) { +let block = function(bool) { return (bool) ? 'block' : 'inline'; } +let safePath = function(path) { + return path.replace(/[^a-zA-Z]+/g, '\\$1') +} + export { checkLength, checkRegex, calcVote, handleSubmit, - calcVoteUser, formatPost, - block + block, + safePath }; \ No newline at end of file diff --git a/src/routes/+layout.svelte b/src/routes/+layout.svelte index 38fa2d9..51c4daf 100644 --- a/src/routes/+layout.svelte +++ b/src/routes/+layout.svelte @@ -1,4 +1,19 @@ -
- - +
+
diff --git a/src/routes/+page.svelte b/src/routes/+page.svelte index f9fae61..d065fc8 100644 --- a/src/routes/+page.svelte +++ b/src/routes/+page.svelte @@ -1,23 +1,8 @@ -{#each data.postJson.data as post} - -{/each} - -

- - -

\ No newline at end of file + \ No newline at end of file diff --git a/src/routes/post/[post]/+page.js b/src/routes/post/[post]/+page.js index 8e45037..961839b 100644 --- a/src/routes/post/[post]/+page.js +++ b/src/routes/post/[post]/+page.js @@ -7,10 +7,8 @@ export async function load({ fetch, params, url }) { await new Promise(resolve => setTimeout(resolve, 100)); - const res = await fetch(`/api/postGet?id=${id}`); + const res = await fetch(`/api/postBulk?id=${id}`); const postJson = (await res.json()); - console.log(postJson); - - return postJson; + return {postJson}; } \ No newline at end of file diff --git a/src/routes/post/[post]/+page.svelte b/src/routes/post/[post]/+page.svelte index 127c837..d065fc8 100644 --- a/src/routes/post/[post]/+page.svelte +++ b/src/routes/post/[post]/+page.svelte @@ -1,15 +1,8 @@ - \ No newline at end of file + + \ No newline at end of file diff --git a/src/routes/user/[user]/+page.js b/src/routes/user/[user]/+page.js index 9fb0dad..062e054 100644 --- a/src/routes/user/[user]/+page.js +++ b/src/routes/user/[user]/+page.js @@ -16,5 +16,5 @@ export async function load({ fetch, params, url }) { const resUser = await fetch(`/api/userGet?user=${user}`); const postJsonUser = (await resUser.json()) || {}; - return { postJson, id, postJsonUser }; + return { postJson, id, postJsonUser, user }; } \ No newline at end of file diff --git a/src/routes/user/[user]/+page.svelte b/src/routes/user/[user]/+page.svelte index 2fe86ce..b73c15a 100644 --- a/src/routes/user/[user]/+page.svelte +++ b/src/routes/user/[user]/+page.svelte @@ -1,6 +1,7 @@