diff --git a/src/lib/Area.svelte b/src/lib/Area.svelte index e4db5fa..cbc8cca 100644 --- a/src/lib/Area.svelte +++ b/src/lib/Area.svelte @@ -26,15 +26,26 @@ #main { min-height: 250px; } + + #main.tiny { + min-height: initial; + height: 100px; + overflow: hidden; + } + + +
-
+

Content

diff --git a/src/lib/Form.svelte b/src/lib/Form.svelte deleted file mode 100644 index 7b35382..0000000 --- a/src/lib/Form.svelte +++ /dev/null @@ -1,15 +0,0 @@ - - - -

- Welcome to SvelteKit -

-

- Visit kit.svelte.dev to read the documentation -

-

- -

- \ No newline at end of file diff --git a/src/lib/Post.svelte b/src/lib/Post.svelte index 7b35382..05f46fe 100644 --- a/src/lib/Post.svelte +++ b/src/lib/Post.svelte @@ -1,15 +1,75 @@ - -

- Welcome to SvelteKit -

-

- Visit kit.svelte.dev to read the documentation -

-

- -

- \ No newline at end of file + + +{#if success} + +

+ Error +

+

+ {success} +

+

+ Failed to get post. +

+ +{:else} + + + + {username} + + + + {#each contentSplit as line} +

{line}

+ {/each} +
+ + + + Upvote + + + {upvotes + 0} + + + + + Downvote + + + {downvotes + 0} + + + {#if id} + + + View + + + {/if} + + +{/if} \ No newline at end of file diff --git a/src/lib/db.js b/src/lib/db.js index be83c9b..d05fb7d 100644 --- a/src/lib/db.js +++ b/src/lib/db.js @@ -1,6 +1,7 @@ import sqlite3 from 'sqlite3' import { open } from 'sqlite' import { hash, compare } from 'bcrypt' +import { calcVote } from './util.js'; const { randomBytes @@ -15,7 +16,7 @@ async function initDb() { await db.run('CREATE TABLE IF NOT EXISTS auth (username CHAR(64), password CHAR(1024))'); await db.run('CREATE TABLE IF NOT EXISTS token (username CHAR(64), token CHAR(1024))'); - await db.run('CREATE TABLE IF NOT EXISTS post (username CHAR(64), id CHAR(64), content CHAR(10240), upvotes INTEGER, downvotes INTEGER)'); + await db.run('CREATE TABLE IF NOT EXISTS post (username CHAR(64), id CHAR(64), content CHAR(10240), upvotes INTEGER, downvotes INTEGER, rating REAL)'); await db.run('CREATE TABLE IF NOT EXISTS vote (id CHAR(64), username CHAR(64), type INTEGER)'); } @@ -67,10 +68,11 @@ async function loginBackend({user, pass}) { async function postCreateBackend({user, content}) { var id = randomBytes(10).toString('hex'); - await db.run('INSERT INTO post (username, id, content) VALUES (?, ?, ?)', [ + await db.run('INSERT INTO post (username, id, content, rating) VALUES (?, ?, ?, ?)', [ user, id, - content + content, + calcVote(0,0) ]) } @@ -86,6 +88,46 @@ async function postGetBackend({id}) { return posts[0]; } +async function postGetBulkBackend({page, rows}) { + var posts = await db.all('SELECT * from post ORDER BY rating DESC LIMIT ?, ?', [ + page*rows, + rows + ]) + + return posts; +} + +async function voteBackend({user, id, vote}) { + if (!user || !id || user == '' || (vote != 'down' && vote != 'up')) return {}; + + await db.run('DELETE FROM vote WHERE username = ? AND id = ?', [ + user, + id + ]); + + await db.run('INSERT INTO vote (id, username, type) VALUES (?,?,?)', [ + id, + user, + vote == 'up' ? 1 : 2 + ]); + + var votes = await db.all('SELECT type from vote WHERE id = ?', [ + id + ]) || []; + + var up = votes.filter(x => x.type == 1).length; + var down = votes.filter(x => x.type == 2).length; + + await db.run('UPDATE post SET upvotes = ?, downvotes = ?, rating = ? WHERE id = ?', [ + up, + down, + calcVote(up,down), + id + ]); + + return {}; +} + async function tokenBackend({token}) { if (!db) await initDb(); @@ -104,5 +146,7 @@ export { loginBackend, tokenBackend, postCreateBackend, - postGetBackend + postGetBackend, + voteBackend, + postGetBulkBackend } \ No newline at end of file diff --git a/src/lib/util.js b/src/lib/util.js index 6726672..6796af8 100644 --- a/src/lib/util.js +++ b/src/lib/util.js @@ -20,7 +20,23 @@ let checkRegex = function(string, field, regex) { return false; } +let calcVote = 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); + + rating = (rating + 10) / 2; + + return rating * Math.log(totalPadded); +} + export { checkLength, - checkRegex + checkRegex, + calcVote }; \ No newline at end of file diff --git a/src/routes/+layout.svelte b/src/routes/+layout.svelte index 74cddc4..75678ea 100644 --- a/src/routes/+layout.svelte +++ b/src/routes/+layout.svelte @@ -46,6 +46,9 @@ flex-direction: row; flex-wrap: wrap; align-items: center; + + position: sticky; + top: 0; } #logo a { diff --git a/src/routes/+page.js b/src/routes/+page.js new file mode 100644 index 0000000..2624bfd --- /dev/null +++ b/src/routes/+page.js @@ -0,0 +1,15 @@ +/** @type {import('./$types').PageLoad} */ +export async function load({ fetch, params, url }) { + var search = url.searchParams; + + var voteType = search.get('vote'); + + var id = search.get('page') * 1; + + await new Promise(resolve => setTimeout(resolve, 100)); + + const res = await fetch(`/api/explore?page=${id}`); + const postJson = await res.json(); + + return { postJson, id }; +} \ No newline at end of file diff --git a/src/routes/+page.svelte b/src/routes/+page.svelte index 7b35382..e21006f 100644 --- a/src/routes/+page.svelte +++ b/src/routes/+page.svelte @@ -1,15 +1,22 @@ - -

- Welcome to SvelteKit -

-

- Visit kit.svelte.dev to read the documentation -

-

- -

- \ No newline at end of file +{#each data.postJson as post} + +{/each} + +

+ Next page +

+

\ No newline at end of file diff --git a/src/routes/api/explore/+server.js b/src/routes/api/explore/+server.js new file mode 100644 index 0000000..0fc0a2d --- /dev/null +++ b/src/routes/api/explore/+server.js @@ -0,0 +1,10 @@ +import { postGetBulkBackend } from '../../../lib/db.js'; + +/** @type {import('./$types').RequestHandler} */ +export async function GET({ url, cookies }) { + var page = url.searchParams.get('page') * 1; + + var postData = await postGetBulkBackend({ rows: 5, page }); + + return new Response(JSON.stringify(postData)); +}; \ No newline at end of file diff --git a/src/routes/api/vote/+server.js b/src/routes/api/vote/+server.js new file mode 100644 index 0000000..3d6a8bf --- /dev/null +++ b/src/routes/api/vote/+server.js @@ -0,0 +1,17 @@ +import { tokenBackend, voteBackend } from '../../../lib/db.js'; + +/** @type {import('./$types').RequestHandler} */ +export async function GET({ url, cookies }) { + var token = cookies.get('token') || ''; + + var user = await tokenBackend({token}); + + if (!user) return; + + var id = url.searchParams.get('post'); + var vote = url.searchParams.get('vote'); + + voteBackend({user,id,vote}); + + return new Response(); +}; \ No newline at end of file diff --git a/src/routes/post/[post]/+page.js b/src/routes/post/[post]/+page.js index 15d705a..4ea67c9 100644 --- a/src/routes/post/[post]/+page.js +++ b/src/routes/post/[post]/+page.js @@ -1,12 +1,19 @@ /** @type {import('./$types').PageLoad} */ export async function load({ fetch, params, url }) { + var search = url.searchParams; + + var voteType = search.get('vote'); + var id = params.post; + + if (voteType) { + await fetch(`/api/vote?post=${id}&vote=${voteType}`); + } + + await new Promise(resolve => setTimeout(resolve, 100)); + const res = await fetch(`/api/post?post=${id}`); const postJson = await res.json(); - var search = url.searchParams; - - var voteType = (search.get('upvote')) ? 1 : ((search.get('downvote')) ? 2 : 0); - - 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 1f89777..823ccb6 100644 --- a/src/routes/post/[post]/+page.svelte +++ b/src/routes/post/[post]/+page.svelte @@ -1,5 +1,5 @@ - - -{#if data.postJson.success} - -

- Error -

-

- {data.postJson.success} -

-

- Failed to get post. -

- -{:else} - -

- - {data.postJson.username} - -

-

- {data.postJson.content} -

-

- - - Upvote - - - {data.postJson.upvotes + 0} - - - - - Downvote - - - {data.postJson.downvotes + 0} - - -

- -{/if} \ No newline at end of file + \ No newline at end of file diff --git a/static/downvote.svg b/static/downvote.svg index 5b92379..baf1bef 100644 --- a/static/downvote.svg +++ b/static/downvote.svg @@ -2,9 +2,9 @@ + transform="translate(-48.929905,-129.52741)"> + style="fill:none;fill-opacity:1;stroke:#ffffff;stroke-width:11.90625;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none;stroke-opacity:1" + d="m 56.684592,149.59814 10.887303,12.1325 13.600048,-26.2501" + id="path3462" /> + style="fill:none;fill-opacity:1;stroke:#ffffff;stroke-width:11.90625;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none;stroke-opacity:1" + d="M 79.370381,172.06252 68.483078,159.93002 54.88303,186.18012" + id="path8000" /> diff --git a/static/upvote.svg b/static/upvote.svg index 0be98bb..41a6538 100644 --- a/static/upvote.svg +++ b/static/upvote.svg @@ -2,9 +2,9 @@ + transform="translate(-47.715969,-129.48962)"> - + style="fill:none;fill-opacity:1;stroke:#ffffff;stroke-width:7.9375;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none;stroke-opacity:1" + d="m 51.684719,147.57597 10.887303,12.1325 13.600048,-26.2501" + id="path3462" /> diff --git a/static/view.svg b/static/view.svg new file mode 100644 index 0000000..a6df2f0 --- /dev/null +++ b/static/view.svg @@ -0,0 +1,54 @@ + + + + + + + + + + +