From 21ccd4983e8e0dde616f57a353c81fc80837e726 Mon Sep 17 00:00:00 2001 From: Xodrium <118943715+malloc62@users.noreply.github.com> Date: Tue, 14 Feb 2023 00:30:10 -0500 Subject: [PATCH] Initialized project This is bad --- .gitignore | 11 ++++ README.md | 0 package.json | 23 +++++++ src/app.html | 15 +++++ src/lib/components/Area.svelte | 71 ++++++++++++++++++++ src/lib/components/Button.svelte | 28 ++++++++ src/lib/components/FileUpload.svelte | 80 ++++++++++++++++++++++ src/lib/components/Header.svelte | 58 ++++++++++++++++ src/lib/db/db.js | 95 +++++++++++++++++++++++++++ src/lib/util.js | 85 ++++++++++++++++++++++++ src/routes/+layout.js | 8 +++ src/routes/+layout.svelte | 46 +++++++++++++ src/routes/+page.server.js | 19 ++++++ src/routes/+page.svelte | 62 +++++++++++++++++ src/routes/api/[route]/+server.js | 51 ++++++++++++++ src/routes/img/[img]/+server.js | 20 ++++++ src/routes/login/+page.svelte | 43 ++++++++++++ static/YourOC.svg | 1 + static/delete.svg | 50 ++++++++++++++ static/downvote.svg | 52 +++++++++++++++ static/favicon.png | Bin 0 -> 1571 bytes static/icon_sanifae.svg | 61 +++++++++++++++++ static/icon_sanifae_black.svg | 61 +++++++++++++++++ static/logo_sanifae.svg | 66 +++++++++++++++++++ static/upvote.svg | 48 ++++++++++++++ static/view.svg | 54 +++++++++++++++ svelte.config.js | 10 +++ vite.config.js | 7 ++ 28 files changed, 1125 insertions(+) create mode 100644 .gitignore create mode 100644 README.md create mode 100644 package.json create mode 100644 src/app.html create mode 100644 src/lib/components/Area.svelte create mode 100644 src/lib/components/Button.svelte create mode 100644 src/lib/components/FileUpload.svelte create mode 100644 src/lib/components/Header.svelte create mode 100644 src/lib/db/db.js create mode 100644 src/lib/util.js create mode 100644 src/routes/+layout.js create mode 100644 src/routes/+layout.svelte create mode 100644 src/routes/+page.server.js create mode 100644 src/routes/+page.svelte create mode 100644 src/routes/api/[route]/+server.js create mode 100644 src/routes/img/[img]/+server.js create mode 100644 src/routes/login/+page.svelte create mode 100644 static/YourOC.svg create mode 100644 static/delete.svg create mode 100644 static/downvote.svg create mode 100644 static/favicon.png create mode 100644 static/icon_sanifae.svg create mode 100644 static/icon_sanifae_black.svg create mode 100644 static/logo_sanifae.svg create mode 100644 static/upvote.svg create mode 100644 static/view.svg create mode 100644 svelte.config.js create mode 100644 vite.config.js diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..42e5a50 --- /dev/null +++ b/.gitignore @@ -0,0 +1,11 @@ +.DS_Store +node_modules +/build +/.svelte-kit +/package +.env +.env.* +!.env.example +vite.config.js.timestamp-* +vite.config.ts.timestamp-* +/db diff --git a/README.md b/README.md new file mode 100644 index 0000000..e69de29 diff --git a/package.json b/package.json new file mode 100644 index 0000000..1a38a32 --- /dev/null +++ b/package.json @@ -0,0 +1,23 @@ +{ + "name": "sanifae", + "version": "0.0.1", + "private": true, + "scripts": { + "dev": "vite dev", + "build": "vite build", + "preview": "vite preview" + }, + "devDependencies": { + "@sveltejs/adapter-auto": "^1.0.0", + "@sveltejs/kit": "^1.0.0", + "svelte": "^3.54.0", + "vite": "^4.0.0" + }, + "type": "module", + "dependencies": { + "@sveltejs/adapter-node": "^1.1.4", + "bcrypt": "^5.1.0", + "sqlite": "^4.1.2", + "sqlite3": "^5.1.4" + } +} diff --git a/src/app.html b/src/app.html new file mode 100644 index 0000000..4c57e56 --- /dev/null +++ b/src/app.html @@ -0,0 +1,15 @@ + + + + + + + + + + %sveltekit.head% + + +
%sveltekit.body%
+ + diff --git a/src/lib/components/Area.svelte b/src/lib/components/Area.svelte new file mode 100644 index 0000000..bc0c3f0 --- /dev/null +++ b/src/lib/components/Area.svelte @@ -0,0 +1,71 @@ + + + + + +
+ +
+ +

Content

+
+
+ +
\ No newline at end of file diff --git a/src/lib/components/Button.svelte b/src/lib/components/Button.svelte new file mode 100644 index 0000000..8e2f6c2 --- /dev/null +++ b/src/lib/components/Button.svelte @@ -0,0 +1,28 @@ + + + + + \ No newline at end of file diff --git a/src/lib/components/FileUpload.svelte b/src/lib/components/FileUpload.svelte new file mode 100644 index 0000000..65cc312 --- /dev/null +++ b/src/lib/components/FileUpload.svelte @@ -0,0 +1,80 @@ + + + + +
+ {#if preview} + Image preview + {:else} + Image preview + {/if} + getBase64(files[0])}/> +

+ Progress: {progress * 100}% +

+

+ +

+
\ No newline at end of file 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/db/db.js b/src/lib/db/db.js new file mode 100644 index 0000000..61b7af1 --- /dev/null +++ b/src/lib/db/db.js @@ -0,0 +1,95 @@ +const FILE_SIZE_LIMIT = 1024*1024*16; + +const VALID_EXTENSIONS = ['png','jpg','jpeg','svg']; + +var ridArray = {}; + +import sqlite3 from 'sqlite3' +import { writeFile } from 'node:fs/promises'; +import { safePath, user } from '../util.js'; +import { open } from 'sqlite' +import { createHash } from 'node:crypto'; + +var db; +async function initDb() { + db = await open({ + filename: `${process.cwd()}/db/main.db`, + driver: sqlite3.Database + }); + + await db.run('CREATE TABLE IF NOT EXISTS rating (id CHAR(256), rating INTEGER)'); +} + +let backendProxy = async ({route, backendParams,}) => { + if (!db) await initDb(); + + const res = await fetch(`https://sanifae.insfa.net/api/token`,{ + 'method': 'GET', 'headers': { + 'cookie': backendParams.cookie + } + }); + + backendParams['admin'] = ((await res.json()).data == user); + + return backend[route](backendParams); +} + +var backend = {}; + + +backend.rateOc = async ({admin,id,rating}) => { + if (admin) { + await db.run('UPDATE rating SET rating = ? WHERE id = ?', [ + rating, + id + ]) + } +}; + +backend.oc = async ({admin}) => { + return await db.all('SELECT * FROM rating WHERE rating > ? ORDER BY rating DESC', [ + (admin) ? -1000 : -1 + ]); +} + +backend.fileCreate = async({img, extension,id, last }) => { + if (ridArray[id] !== '' && !(ridArray[id])) { + ridArray[id] = img; + } else { + ridArray[id] += img; + } + + const imgData = ridArray[id]; + + if (last != 'true') { + return {'success': 'Image still proccessing...'} + } else { + ridArray[id] = false; + } + + const imgHash = createHash('md5').update(imgData).digest('hex'); + + if (!imgHash) + return {'success': 'Image not provided.'} + + if (imgHash.length > FILE_SIZE_LIMIT) + return {'success': 'Image too big.'} + + const extensionSafe = safePath(extension); + + if (VALID_EXTENSIONS.indexOf(extensionSafe) == -1) + return { success: 'Illegal file extension. Permitted file extensions are: ' + VALID_EXTENSIONS.join(', ') }; + + writeFile(`${process.cwd()}/db/post-${imgHash}.${extensionSafe}`,imgData,{encoding: 'base64'}); + + await db.run('INSERT INTO rating (id,rating) VALUES (?,?)', [ + `${imgHash}.${extensionSafe}`, + -1 + ]); + + return { success: 'Successfully uploaded file.', 'href': `/img/${imgHash}.${extensionSafe}`}; +} +export { + backendProxy, + backend +} \ No newline at end of file diff --git a/src/lib/util.js b/src/lib/util.js new file mode 100644 index 0000000..3503b1e --- /dev/null +++ b/src/lib/util.js @@ -0,0 +1,85 @@ +const EXTENSION_MAP = { + 'png': 'img', + 'jpg': 'img', + 'jpeg': 'img', + 'gif': 'img', + 'svg': 'img', + 'mp4': 'video' +} + +let checkLength = function(string, field, lowerBound, upperBound) { + if (string.length < lowerBound) { + if (string.length == 0) { + return { success: `${field} cannot be blank.` } + } + return { success: `${field} is too short (minimum length: ${lowerBound} characters).` } + } + + if (string.length > upperBound) { + return { success: `${field} is too long (maximum length: ${upperBound} characters).` } + } + + return false; +} + +let checkRegex = function(string, field, regex) { + if (string.search(regex) != -1) { + return { success: `${field} contains illegal characters.` } + } + return false; +} + +let handleSubmitGet = async e => { + const ACTION_URL = e.target.action + + const formData = new FormData(e.target); + const asString = new URLSearchParams(formData).toString(); + + return await fetch(ACTION_URL + '?' + asString, { + method: 'GET', + }).then(x => x.text()); +} + +let handleSubmit = async e => { + const ACTION_URL = e.target.action + + const formData = new FormData(e.target); + + return await fetch(ACTION_URL, { + method: 'POST', + body: formData + }).then(x => x.text()); +} + +let safeName = function (text) { + return text.replaceAll(/[^A-Za-z0-9\-\_]/g, ''); +} + +let block = function(bool) { + return (bool) ? 'block' : 'inline'; +} + +let safePath = function(path) { + if (path == '..' || path == '.') return ''; + return path.replace(/[\/]+/g, '') +} + +let setLocation = function(location, key, value) { + var loc = new URL(location).searchParams; + + loc.set(key,value); + return loc.toString(); +} + +let user = 'derv'; + +export { + checkLength, + checkRegex, + handleSubmit, + handleSubmitGet, + block, + safePath, + setLocation, + user +}; \ No newline at end of file diff --git a/src/routes/+layout.js b/src/routes/+layout.js new file mode 100644 index 0000000..a0c8ba5 --- /dev/null +++ b/src/routes/+layout.js @@ -0,0 +1,8 @@ +/** @type {import('./$types').PageLoad} */ +export async function load({ fetch }) { + const res = await fetch(`/api/token`); + + const username = await res.json(); + + return { username: username.data }; +} \ No newline at end of file diff --git a/src/routes/+layout.svelte b/src/routes/+layout.svelte new file mode 100644 index 0000000..c431840 --- /dev/null +++ b/src/routes/+layout.svelte @@ -0,0 +1,46 @@ + + +
+ +
+ diff --git a/src/routes/+page.server.js b/src/routes/+page.server.js new file mode 100644 index 0000000..7d482a4 --- /dev/null +++ b/src/routes/+page.server.js @@ -0,0 +1,19 @@ +import { user } from '$lib/util.js'; + +/** @type {import('./$types').PageServerLoad} */ +export async function load({ fetch, params, url, cookies, request }) { + + const res = await fetch(`https://sanifae.insfa.net/api/token`,{ + 'method': 'GET', 'headers': { + 'cookie': request.headers.get('cookie') + } + }); + + const userJson = await res.json(); + + const oc = await fetch(`/api/oc?user=${encodeURIComponent(user)}`,{ + 'method': 'GET' + }).then(x => x.json()); + + return { data: userJson.data == user, oc, token: request.headers.get('cookie') }; +} \ No newline at end of file diff --git a/src/routes/+page.svelte b/src/routes/+page.svelte new file mode 100644 index 0000000..97562e5 --- /dev/null +++ b/src/routes/+page.svelte @@ -0,0 +1,62 @@ + + + + + +
+ OC Rating Stand +
+
+

Put your OC and wait for it to be rated! SVGs (vector), PNGs (bitmap), and other image formats can be uploaded.

+ +
+
+ Project of INSFA +
+ + + +
+ Rated OCs +
+
+ {#each data.oc as ocData} +
+ +

+ + {ocData.rating == '-1' ? 'Unrated' : ocData.rating} + / 10 +

+ +
+ {/each} +
+
+ +
+ \ No newline at end of file diff --git a/src/routes/api/[route]/+server.js b/src/routes/api/[route]/+server.js new file mode 100644 index 0000000..563587f --- /dev/null +++ b/src/routes/api/[route]/+server.js @@ -0,0 +1,51 @@ +import { backend, backendProxy } from '../../../lib/db/db.js'; + + +/** @type {import('./$types').RequestHandler} */ +export async function GET({ url, cookies, params, fetch, request }) { + var formEntries = url.searchParams; + + formEntries = [...formEntries,['cookie',request.headers.get('cookie')]]; + + return await handleReq({ + cookies, + params: formEntries, + route: params.route, + fetch + }); +} + +/** @type {import('./$types').RequestHandler} */ +export async function POST({ cookies, request, params, fetch }) { + + var formEntries = (await request.formData()).entries(); + + formEntries = [...formEntries,['cookie',request.headers.get('cookie')]]; + + return await handleReq({ + cookies, + params: formEntries, + route: params.route, + fetch + }); +} + +async function handleReq({ cookies, params, route, fetch }) { + var backendParams = {cookies,fetch}; + + for (const [key, value] of params) { + backendParams[key] = value + ''; + } + + return await mainApi({backendParams, route: route}); +} + +async function mainApi({backendParams, route, fetch}) { + if (Object.keys(backend).indexOf(route) == -1) { + return new Response(JSON.stringify({success: 'route doesn\'t exist'})); + } + + var resData = await backendProxy({ route, backendParams }); + + return new Response(JSON.stringify(resData)); +}; \ No newline at end of file diff --git a/src/routes/img/[img]/+server.js b/src/routes/img/[img]/+server.js new file mode 100644 index 0000000..eaf5df7 --- /dev/null +++ b/src/routes/img/[img]/+server.js @@ -0,0 +1,20 @@ +import { readFile } from 'node:fs/promises'; + +/** @type {import('./$types').RequestHandler} */ +export async function GET({ url, cookies, params }) { + var imgName = params['img']; + + imgName = imgName.replace(/(\s+)/g, '\\$1'); + + var res = await readFile(`${process.cwd()}/db/post-${imgName}`); + + var response = new Response(res); + var extension = imgName.split('.').pop(); + + if (extension == 'svg') { + response = new Response(res, {'headers': { + 'Content-Type': 'image/svg+xml' + }}); + } + return response; +} diff --git a/src/routes/login/+page.svelte b/src/routes/login/+page.svelte new file mode 100644 index 0000000..8e34067 --- /dev/null +++ b/src/routes/login/+page.svelte @@ -0,0 +1,43 @@ + + + +

+ Log in +

+ + +

Login with Sanifae

+
+

+ Username: +

+

+ Password: +

+

+ +

+
+
+

+ {#if form?.success} +

{form?.success}

+ {/if} + By using the Sanifae service, you agree to the Terms of Service. +

+ \ No newline at end of file diff --git a/static/YourOC.svg b/static/YourOC.svg new file mode 100644 index 0000000..62323a6 --- /dev/null +++ b/static/YourOC.svg @@ -0,0 +1 @@ +Your OC \ No newline at end of file diff --git a/static/delete.svg b/static/delete.svg new file mode 100644 index 0000000..218d0fe --- /dev/null +++ b/static/delete.svg @@ -0,0 +1,50 @@ + + + + + + + + + + diff --git a/static/downvote.svg b/static/downvote.svg new file mode 100644 index 0000000..4ef8081 --- /dev/null +++ b/static/downvote.svg @@ -0,0 +1,52 @@ + + + + + + + + + + + diff --git a/static/favicon.png b/static/favicon.png new file mode 100644 index 0000000000000000000000000000000000000000..825b9e65af7c104cfb07089bb28659393b4f2097 GIT binary patch literal 1571 zcmV+;2Hg3HP)Px)-AP12RCwC$UE6KzI1p6{F2N z1VK2vi|pOpn{~#djwYcWXTI_im_u^TJgMZ4JMOsSj!0ma>B?-(Hr@X&W@|R-$}W@Z zgj#$x=!~7LGqHW?IO8+*oE1MyDp!G=L0#^lUx?;!fXv@l^6SvTnf^ac{5OurzC#ZMYc20lI%HhX816AYVs1T3heS1*WaWH z%;x>)-J}YB5#CLzU@GBR6sXYrD>Vw(Fmt#|JP;+}<#6b63Ike{Fuo!?M{yEffez;| zp!PfsuaC)>h>-AdbnwN13g*1LowNjT5?+lFVd#9$!8Z9HA|$*6dQ8EHLu}U|obW6f z2%uGv?vr=KNq7YYa2Roj;|zooo<)lf=&2yxM@e`kM$CmCR#x>gI>I|*Ubr({5Y^rb zghxQU22N}F51}^yfDSt786oMTc!W&V;d?76)9KXX1 z+6Okem(d}YXmmOiZq$!IPk5t8nnS{%?+vDFz3BevmFNgpIod~R{>@#@5x9zJKEHLHv!gHeK~n)Ld!M8DB|Kfe%~123&Hz1Z(86nU7*G5chmyDe ziV7$pB7pJ=96hpxHv9rCR29%bLOXlKU<_13_M8x)6;P8E1Kz6G<&P?$P^%c!M5`2` zfY2zg;VK5~^>TJGQzc+33-n~gKt{{of8GzUkWmU110IgI0DLxRIM>0US|TsM=L|@F z0Bun8U!cRB7-2apz=y-7*UxOxz@Z0)@QM)9wSGki1AZ38ceG7Q72z5`i;i=J`ILzL z@iUO?SBBG-0cQuo+an4TsLy-g-x;8P4UVwk|D8{W@U1Zi z!M)+jqy@nQ$p?5tsHp-6J304Q={v-B>66$P0IDx&YT(`IcZ~bZfmn11#rXd7<5s}y zBi9eim&zQc0Dk|2>$bs0PnLmDfMP5lcXRY&cvJ=zKxI^f0%-d$tD!`LBf9^jMSYUA zI8U?CWdY@}cRq6{5~y+)#h1!*-HcGW@+gZ4B};0OnC~`xQOyH19z*TA!!BJ%9s0V3F?CAJ{hTd#*tf+ur-W9MOURF-@B77_-OshsY}6 zOXRY=5%C^*26z?l)1=$bz30!so5tfABdSYzO+H=CpV~aaUefmjvfZ3Ttu9W&W3Iu6 zROlh0MFA5h;my}8lB0tAV-Rvc2Zs_CCSJnx@d`**$idgy-iMob4dJWWw|21b4NB=LfsYp0Aeh{Ov)yztQi;eL4y5 zMi>8^SzKqk8~k?UiQK^^-5d8c%bV?$F8%X~czyiaKCI2=UH + + + + + + + + + + + + diff --git a/static/icon_sanifae_black.svg b/static/icon_sanifae_black.svg new file mode 100644 index 0000000..b8f8bbe --- /dev/null +++ b/static/icon_sanifae_black.svg @@ -0,0 +1,61 @@ + + + + + + + + + + + + + diff --git a/static/logo_sanifae.svg b/static/logo_sanifae.svg new file mode 100644 index 0000000..54e106f --- /dev/null +++ b/static/logo_sanifae.svg @@ -0,0 +1,66 @@ + + + + + + + + + + + + + + diff --git a/static/upvote.svg b/static/upvote.svg new file mode 100644 index 0000000..8e113b7 --- /dev/null +++ b/static/upvote.svg @@ -0,0 +1,48 @@ + + + + + + + + + + diff --git a/static/view.svg b/static/view.svg new file mode 100644 index 0000000..c181cc3 --- /dev/null +++ b/static/view.svg @@ -0,0 +1,54 @@ + + + + + + + + + + + diff --git a/svelte.config.js b/svelte.config.js new file mode 100644 index 0000000..6bfb3c4 --- /dev/null +++ b/svelte.config.js @@ -0,0 +1,10 @@ +import adapter from '@sveltejs/adapter-node'; + +/** @type {import('@sveltejs/kit').Config} */ +const config = { + kit: { + adapter: adapter() + } +}; + +export default config; diff --git a/vite.config.js b/vite.config.js new file mode 100644 index 0000000..11f6c22 --- /dev/null +++ b/vite.config.js @@ -0,0 +1,7 @@ +import { sveltekit } from '@sveltejs/kit/vite'; + +const config = { + plugins: [sveltekit()] +}; + +export default config;