Added profile pictures
This commit is contained in:
parent
908055a85b
commit
06fedb4387
6 changed files with 108 additions and 36 deletions
|
@ -30,6 +30,7 @@
|
||||||
#header {
|
#header {
|
||||||
border-bottom: var(--dark-2) solid 2px;
|
border-bottom: var(--dark-2) solid 2px;
|
||||||
width: calc(100% - 30px);
|
width: calc(100% - 30px);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#main {
|
#main {
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
<script>
|
<script>
|
||||||
import Button from '$lib/components/Button.svelte';
|
import Button from '$lib/components/Button.svelte';
|
||||||
|
|
||||||
export let form;
|
export let form, apiUrl, type;
|
||||||
|
|
||||||
let fileInput;
|
let fileInput;
|
||||||
let files;
|
let files;
|
||||||
|
@ -41,7 +41,7 @@
|
||||||
fData.append('last',i == (images.length - 1));
|
fData.append('last',i == (images.length - 1));
|
||||||
fData.append('id',rId);
|
fData.append('id',rId);
|
||||||
|
|
||||||
form = await fetch(`/api/fileCreate`, {
|
form = await fetch(apiUrl || `/api/fileCreate`, {
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
body: fData,
|
body: fData,
|
||||||
}).then(x => x.json());
|
}).then(x => x.json());
|
||||||
|
@ -62,9 +62,13 @@
|
||||||
img {
|
img {
|
||||||
max-width: 250px;
|
max-width: 250px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.small img {
|
||||||
|
max-width: 50px;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
<form action='#' method='GET' >
|
<form action='#' method='GET' class='{type || ''}' >
|
||||||
{#if preview}
|
{#if preview}
|
||||||
<img src={preview} alt="Image preview"/>
|
<img src={preview} alt="Image preview"/>
|
||||||
{:else}
|
{:else}
|
||||||
|
|
|
@ -5,6 +5,7 @@ const AUTH_ACTIONS = [
|
||||||
'fileCreate',
|
'fileCreate',
|
||||||
'vote',
|
'vote',
|
||||||
'postDelete',
|
'postDelete',
|
||||||
|
'pfp',
|
||||||
'follow'
|
'follow'
|
||||||
];
|
];
|
||||||
|
|
||||||
|
@ -349,39 +350,54 @@ backend.follow = async ({target, user}) => {
|
||||||
return {'success': 'User followed/unfollowed.', 'data': {following, followers}};
|
return {'success': 'User followed/unfollowed.', 'data': {following, followers}};
|
||||||
};
|
};
|
||||||
|
|
||||||
backend.fileCreate = async({img, extension,id, last }) => {
|
let fileCreate = (type) => {
|
||||||
if (ridArray[id] !== '' && !(ridArray[id])) {
|
return async ({img, extension,id, last, user }) => {
|
||||||
ridArray[id] = img;
|
let validExtensions = VALID_EXTENSIONS;
|
||||||
} else {
|
|
||||||
ridArray[id] += img;
|
if (type == 'pfp') validExtensions = ['png'];
|
||||||
|
|
||||||
|
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 (validExtensions.indexOf(extensionSafe) == -1)
|
||||||
|
return { success: 'Illegal file extension. Permitted file extensions are: ' + validExtensions.join(', ') };
|
||||||
|
|
||||||
|
if (type == 'post') {
|
||||||
|
writeFile(`${process.cwd()}/db/post-${imgHash}.${extensionSafe}`,imgData,{encoding: 'base64'});
|
||||||
|
} else {
|
||||||
|
writeFile(`${process.cwd()}/db/pfp-${user}.png`,imgData,{encoding: 'base64'});
|
||||||
|
}
|
||||||
|
|
||||||
|
return { success: 'Successfully uploaded file.', 'href': `/img/${imgHash}.${extensionSafe}`};
|
||||||
}
|
}
|
||||||
|
|
||||||
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'});
|
|
||||||
|
|
||||||
return { success: 'Successfully uploaded file.', 'href': `/img/${imgHash}.${extensionSafe}`};
|
|
||||||
}
|
}
|
||||||
|
backend.fileCreate = fileCreate('post');
|
||||||
|
backend.pfp = fileCreate('pfp');
|
||||||
|
|
||||||
|
|
||||||
export {
|
export {
|
||||||
backendProxy,
|
backendProxy,
|
||||||
backend
|
backend,
|
||||||
|
VALID_EXTENSIONS
|
||||||
}
|
}
|
24
src/routes/pfp/[img]/+server.js
Normal file
24
src/routes/pfp/[img]/+server.js
Normal file
|
@ -0,0 +1,24 @@
|
||||||
|
import { VALID_EXTENSIONS } from '../../../lib/db/db.js';
|
||||||
|
|
||||||
|
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;
|
||||||
|
|
||||||
|
var res = await readFile(`${process.cwd()}/db/pfp-${imgName}`);
|
||||||
|
|
||||||
|
var response = new Response(res);
|
||||||
|
var extension = imgName.split('.').pop();
|
||||||
|
|
||||||
|
if (extension == 'svg') {
|
||||||
|
response = new Response(res, {'headers': {
|
||||||
|
'Content-Type': 'image/png'
|
||||||
|
}});
|
||||||
|
}
|
||||||
|
return response;
|
||||||
|
}
|
|
@ -20,5 +20,8 @@ export async function load({ fetch, params, url }) {
|
||||||
const resUserBio = await fetch(`/api/userBio?user=${user}`);
|
const resUserBio = await fetch(`/api/userBio?user=${user}`);
|
||||||
const postJsonUserBio = (await resUserBio.json()) || {};
|
const postJsonUserBio = (await resUserBio.json()) || {};
|
||||||
|
|
||||||
return { postJson, id, postJsonUser, postJsonUserBio, user };
|
const resAccData = await fetch(`/api/token`);
|
||||||
|
const resAcc = (await resAccData.json()) || {};
|
||||||
|
|
||||||
|
return { resAcc, postJson, id, postJsonUser, postJsonUserBio, user };
|
||||||
}
|
}
|
|
@ -2,10 +2,13 @@
|
||||||
import Button from '$lib/components/Button.svelte'
|
import Button from '$lib/components/Button.svelte'
|
||||||
import Area from '$lib/components/Area.svelte';
|
import Area from '$lib/components/Area.svelte';
|
||||||
import PostList from '$lib/components/PostList.svelte';
|
import PostList from '$lib/components/PostList.svelte';
|
||||||
|
import FileUpload from '$lib/components/FileUpload.svelte';
|
||||||
|
|
||||||
/** @type {import('./$types').PageData} */
|
/** @type {import('./$types').PageData} */
|
||||||
export let data;
|
export let data;
|
||||||
|
|
||||||
|
let uploadForm = {};
|
||||||
|
|
||||||
let userData = data.postJsonUser.data;
|
let userData = data.postJsonUser.data;
|
||||||
let userBio = data.postJsonUserBio.data;
|
let userBio = data.postJsonUserBio.data;
|
||||||
|
|
||||||
|
@ -32,16 +35,29 @@
|
||||||
.follower {
|
.follower {
|
||||||
margin-right: 1.5rem;
|
margin-right: 1.5rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.pfp {
|
||||||
|
width: 50px;
|
||||||
|
height: 50px;
|
||||||
|
margin-right: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#header {
|
||||||
|
display: flex;
|
||||||
|
align-content: center;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
{#if userData}
|
{#if userData}
|
||||||
<Area>
|
<Area>
|
||||||
<span slot="header">
|
<span slot="header" id='header'>
|
||||||
|
<img class='pfp' src='/pfp/{userData.username}.png'/>
|
||||||
<a href='/users/{userData.username}'>
|
<a href='/users/{userData.username}'>
|
||||||
{userData.username}
|
{userData.username}
|
||||||
</a>
|
</a>
|
||||||
</span>
|
</span>
|
||||||
<span slot="main">
|
<span slot="main">
|
||||||
|
<div class='left'></div>
|
||||||
<p>
|
<p>
|
||||||
<b>Reputation:</b> {userData.reputation}
|
<b>Reputation:</b> {userData.reputation}
|
||||||
</p>
|
</p>
|
||||||
|
@ -57,13 +73,21 @@
|
||||||
|
|
||||||
<h2>Following</h2>
|
<h2>Following</h2>
|
||||||
{#each following as user}
|
{#each following as user}
|
||||||
<a class='follower' href='/user/{user.following}'>{user.following}</a>
|
<a class='follower' href='/user/{user.following}'>
|
||||||
|
<img class='pfp' src='/pfp/{user.following}.png'/>
|
||||||
|
</a>
|
||||||
{/each}
|
{/each}
|
||||||
|
|
||||||
<h2>Followers</h2>
|
<h2>Followers</h2>
|
||||||
{#each followers as user}
|
{#each followers as user}
|
||||||
<a class='follower' href='/user/{user.username}'>{user.username}</a>
|
<a class='follower' href='/user/{user.username}'>
|
||||||
|
<img class='pfp' src='/pfp/{user.username}.png'/>
|
||||||
|
</a>
|
||||||
{/each}
|
{/each}
|
||||||
|
{#if data.resAcc.data == userData.username}
|
||||||
|
<h2>Set PFP</h2>
|
||||||
|
<FileUpload bind:form={uploadForm} type='small' apiUrl={'/api/pfp'}/>
|
||||||
|
{/if}
|
||||||
</span>
|
</span>
|
||||||
<span slot="footer">
|
<span slot="footer">
|
||||||
<Button clickFunc={follow}>
|
<Button clickFunc={follow}>
|
||||||
|
|
Loading…
Reference in a new issue