From 861c03b85160972431ca9b262345d15edecf9acb Mon Sep 17 00:00:00 2001 From: Fuwn Date: Tue, 24 Oct 2023 17:12:54 -0700 Subject: feat: badge wall --- src/lib/userBadgesDatabase.ts | 57 +++++ src/routes/api/badges/add/+server.ts | 23 ++ src/routes/api/badges/remove/+server.ts | 22 ++ src/routes/user/[user]/+page.server.ts | 5 + src/routes/user/[user]/+page.svelte | 40 ++++ src/routes/user/[user]/badges/+page.server.ts | 11 + src/routes/user/[user]/badges/+page.svelte | 301 ++++++++++++++++++++++++++ 7 files changed, 459 insertions(+) create mode 100644 src/lib/userBadgesDatabase.ts create mode 100644 src/routes/api/badges/add/+server.ts create mode 100644 src/routes/api/badges/remove/+server.ts create mode 100644 src/routes/user/[user]/+page.server.ts create mode 100644 src/routes/user/[user]/+page.svelte create mode 100644 src/routes/user/[user]/badges/+page.server.ts create mode 100644 src/routes/user/[user]/badges/+page.svelte (limited to 'src') diff --git a/src/lib/userBadgesDatabase.ts b/src/lib/userBadgesDatabase.ts new file mode 100644 index 00000000..c129770e --- /dev/null +++ b/src/lib/userBadgesDatabase.ts @@ -0,0 +1,57 @@ +import { dev } from '$app/environment'; +import Database from 'better-sqlite3'; + +export interface Badge { + post: string; + image: string; + description?: string; + id?: number; +} + +const database = new Database('./due_moe.sqlite3', { + verbose: dev ? console.log : undefined +}); + +database.exec(`create table if not exists user_badges ( + id integer primary key, + user_id integer not null, + post text not null, + image text not null, + description text default null, + time timestamp default current_timestamp +)`); + +export const getUserBadges = (userId: number): Badge[] => { + return database + .prepare('select * from user_badges where user_id = ?') + .all(String(userId)) as Badge[]; +}; + +export const addUserBadge = (userId: number, badge: Badge) => { + const { post, image, description } = badge; + const statement = database.prepare(` + insert into user_badges (user_id, post, image, description) values (?, ?, ?, ?) + `); + + statement.run(userId, post, image, description); +}; + +export const addUserBadges = (userId: number, badges: Badge[]) => { + const statement = database.prepare(` + insert into user_badges (user_id, post, image, description) values (?, ?, ?, ?) + `); + + for (const badge of badges) { + const { post, image, description } = badge; + + statement.run(userId, post, image, description); + } +}; + +export const removeUserBadge = (userId: number, id: number) => { + if (!isNaN(id)) { + const statement = database.prepare('delete from user_badges where user_id = ? and id = ?'); + + statement.run(userId, id); + } +}; diff --git a/src/routes/api/badges/add/+server.ts b/src/routes/api/badges/add/+server.ts new file mode 100644 index 00000000..6ce9421e --- /dev/null +++ b/src/routes/api/badges/add/+server.ts @@ -0,0 +1,23 @@ +import { userIdentity } from '$lib/AniList/identity.js'; +import { addUserBadges } from '$lib/userBadgesDatabase.js'; + +export const POST = async ({ cookies, request }) => { + const userCookie = cookies.get('user'); + + if (!userCookie) { + return new Response('Unauthenticated', { status: 401 }); + } + + const user = JSON.parse(userCookie); + const identity = await userIdentity({ + tokenType: user['token_type'], + expiresIn: user['expires_in'], + accessToken: user['access_token'], + refreshToken: user['refresh_token'] + }); + const formData = await request.json(); + + addUserBadges(identity.id, formData); + + return Response.json({}); +}; diff --git a/src/routes/api/badges/remove/+server.ts b/src/routes/api/badges/remove/+server.ts new file mode 100644 index 00000000..8b05369a --- /dev/null +++ b/src/routes/api/badges/remove/+server.ts @@ -0,0 +1,22 @@ +import { userIdentity } from '$lib/AniList/identity.js'; +import { removeUserBadge } from '$lib/userBadgesDatabase.js'; + +export const POST = async ({ url, cookies }) => { + const userCookie = cookies.get('user'); + + if (!userCookie) { + return new Response('Unauthenticated', { status: 401 }); + } + + const user = JSON.parse(userCookie); + const identity = await userIdentity({ + tokenType: user['token_type'], + expiresIn: user['expires_in'], + accessToken: user['access_token'], + refreshToken: user['refresh_token'] + }); + + removeUserBadge(identity.id, Number(url.searchParams.get('id'))); + + return Response.json({}); +}; diff --git a/src/routes/user/[user]/+page.server.ts b/src/routes/user/[user]/+page.server.ts new file mode 100644 index 00000000..76d2d889 --- /dev/null +++ b/src/routes/user/[user]/+page.server.ts @@ -0,0 +1,5 @@ +export const load = ({ params }) => { + return { + username: params.user + }; +}; diff --git a/src/routes/user/[user]/+page.svelte b/src/routes/user/[user]/+page.svelte new file mode 100644 index 00000000..227ba252 --- /dev/null +++ b/src/routes/user/[user]/+page.svelte @@ -0,0 +1,40 @@ + + +{#if userData === null} + Could not load user profile for @{data.username}. + +

+ + Does this user exist? +{:else if userData === undefined} + Loading ... +{:else} +

+ @{userData.name} + • Badge Wall +

+ + This user has watched {(userData.statistics.anime.minutesWatched / 60 / 24).toFixed(1)} days of anime + and read + {((userData.statistics.manga.chaptersRead * 8.58) / 60 / 24).toFixed(1)} days of manga. +{/if} diff --git a/src/routes/user/[user]/badges/+page.server.ts b/src/routes/user/[user]/badges/+page.server.ts new file mode 100644 index 00000000..4be5bcd2 --- /dev/null +++ b/src/routes/user/[user]/badges/+page.server.ts @@ -0,0 +1,11 @@ +import { user } from '$lib/AniList/user.js'; +import { getUserBadges } from '$lib/userBadgesDatabase.js'; + +export const load = async ({ params }) => { + const badges = getUserBadges((await user(params.user)).id); + + return { + username: params.user, + badges + }; +}; diff --git a/src/routes/user/[user]/badges/+page.svelte b/src/routes/user/[user]/badges/+page.svelte new file mode 100644 index 00000000..276bf1ca --- /dev/null +++ b/src/routes/user/[user]/badges/+page.svelte @@ -0,0 +1,301 @@ + + +{#await currentUserIdentity} + Loading ... +{:then identity} + {@const isOwner = identity && identity.name === data.username} +

+ Back to Profile + {#if isOwner} + • + (editMode = !editMode)} + >{editMode ? 'Disable' : 'Enable'} Edit Mode + {/if} +

+ + {#if editMode && isOwner} +

+ Delete mode is enabled. Click on an image to delete it. There is no confirmation, so be + careful! +

+ +

+ + + + Add Badge +

+ {/if} + +
+ {#each data.badges as badge} + {#if editMode} + removeBadge(badge)} id={`badge-${badge.id}`}> + {badge.description} + + {:else} + + {badge.description} + + {/if} + {/each} +
+{/await} + + -- cgit v1.2.3 From ab00423409358eace0aa66017bfb252cdf680fd5 Mon Sep 17 00:00:00 2001 From: Fuwn Date: Tue, 24 Oct 2023 17:23:09 -0700 Subject: feat(badges): add safe limits --- src/lib/userBadgesDatabase.ts | 6 +++--- src/routes/user/[user]/badges/+page.svelte | 34 ++++++++++++++++++------------ 2 files changed, 23 insertions(+), 17 deletions(-) (limited to 'src') diff --git a/src/lib/userBadgesDatabase.ts b/src/lib/userBadgesDatabase.ts index c129770e..ae1b1176 100644 --- a/src/lib/userBadgesDatabase.ts +++ b/src/lib/userBadgesDatabase.ts @@ -15,9 +15,9 @@ const database = new Database('./due_moe.sqlite3', { database.exec(`create table if not exists user_badges ( id integer primary key, user_id integer not null, - post text not null, - image text not null, - description text default null, + post text(1000) not null, + image text(1000) not null, + description text(1000) default null, time timestamp default current_timestamp )`); diff --git a/src/routes/user/[user]/badges/+page.svelte b/src/routes/user/[user]/badges/+page.svelte index 276bf1ca..8ed7b878 100644 --- a/src/routes/user/[user]/badges/+page.svelte +++ b/src/routes/user/[user]/badges/+page.svelte @@ -186,18 +186,12 @@ // } // ]; - // onMount(async () => { - // const id = (await user(data.username)).id; - - // for (const badge of badges) { - // await fetch(`/api/badges-add?id=${id}`, { - // method: 'POST', - // body: JSON.stringify(badge) - // }); - // } - // }); - onMount(async () => { + // await fetch(`/api/badges/add`, { + // method: 'POST', + // body: JSON.stringify(badges) + // }); + if (data.user) { currentUserIdentity = userIdentity(data.user); } else { @@ -258,9 +252,21 @@

- - - + + + Add Badge

{/if} -- cgit v1.2.3 From f7ac01d320e825e0ee7962149923614fb37af843 Mon Sep 17 00:00:00 2001 From: Fuwn Date: Tue, 24 Oct 2023 17:24:48 -0700 Subject: feat(badges): remove test values --- src/routes/user/[user]/badges/+page.svelte | 183 ----------------------------- 1 file changed, 183 deletions(-) (limited to 'src') diff --git a/src/routes/user/[user]/badges/+page.svelte b/src/routes/user/[user]/badges/+page.svelte index 8ed7b878..293a7ba5 100644 --- a/src/routes/user/[user]/badges/+page.svelte +++ b/src/routes/user/[user]/badges/+page.svelte @@ -8,190 +8,7 @@ let editMode = false; let currentUserIdentity: ReturnType; - // const badges: Badge[] = [ - // { - // post: 'https://anilist.co/activity/611973592', - // image: 'https://files.catbox.moe/6tvw17.png' - // }, - // { post: 'https://anilist.co/activity/611972285', image: 'https://files.catbox.moe/rn5qr5.png' }, - // { post: 'https://anilist.co/activity/611977824', image: 'https://i.imgur.com/DFkT4zB.png' }, - // { - // post: 'https://anilist.co/activity/612036793', - // image: - // 'https://cdn.discordapp.com/attachments/1136989514653519924/1144851101414326333/Badge2_26-08-23.png' - // }, - // { - // post: 'https://anilist.co/activity/612273794', - // image: - // 'https://cdn.discordapp.com/attachments/1118627570074800264/1144773312468234351/DOGDAY_5_v2.png' - // }, - // { post: 'https://anilist.co/activity/613961295', image: 'https://files.catbox.moe/6rebg8.png' }, - // { post: 'https://anilist.co/activity/614793182', image: 'https://imgur.com/QhJbw4l.png' }, - // { post: 'https://anilist.co/activity/615002857', image: 'https://files.catbox.moe/oc8g02.png' }, - // { post: 'https://anilist.co/activity/615426233', image: 'https://files.catbox.moe/4z226e.png' }, - // { post: 'https://anilist.co/activity/615427328', image: 'https://files.catbox.moe/tqcltp.png' }, - // { post: 'https://anilist.co/activity/615920191', image: 'https://files.catbox.moe/frw5p5.png' }, - // { post: 'https://anilist.co/activity/616629257', image: 'https://files.catbox.moe/15st7d.png' }, - // { post: 'https://anilist.co/activity/617442391', image: 'https://i.imgur.com/aHkSRCz.gif' }, - // { - // post: 'https://anilist.co/activity/617445099', - // image: - // 'https://cdn.discordapp.com/attachments/1118627570074800264/1148663790452346961/chondyunbday.gif' - // }, - // { - // post: 'https://anilist.co/activity/617616590', - // image: - // 'https://cdn.discordapp.com/attachments/1136989514653519924/1148678438551568444/Badge_3.png' - // }, - // { post: 'https://anilist.co/activity/617842237', image: 'https://i.imgur.com/Zx4uiAz.gif' }, - // { post: 'https://anilist.co/activity/618296369', image: 'https://i.imgur.com/V6UsqYI.gif' }, - // { post: 'https://anilist.co/activity/618664650', image: 'https://imgur.com/x98vT7p.png' }, - // { post: 'https://anilist.co/activity/619306471', image: 'https://i.imgur.com/GppbpqE.png' }, - // { post: 'https://anilist.co/activity/619657632', image: 'https://files.catbox.moe/barla6.png' }, - // { post: 'https://anilist.co/activity/619659847', image: 'https://i.imgur.com/e81dgSB.gif' }, - // { post: 'https://anilist.co/activity/619661657', image: 'https://i.imgur.com/S0fSeD4.gif' }, - // { post: 'https://anilist.co/activity/619664832', image: 'https://i.imgur.com/EXNQE3n.gif' }, - // { - // post: 'https://anilist.co/activity/619764622', - // image: - // 'https://cdn.discordapp.com/attachments/1118627570074800264/1151314632942817290/persona_5_3.png' - // }, - // { post: 'https://anilist.co/activity/620025361', image: 'https://i.imgur.com/DmEl13g.gif' }, - // { post: 'https://anilist.co/activity/620125206', image: 'https://i.imgur.com/SmzhGyu.gif' }, - // { post: 'https://anilist.co/activity/620125762', image: 'https://i.imgur.com/38I5gUM.gif' }, - // { post: 'https://anilist.co/activity/620126356', image: 'https://i.imgur.com/9I7Xggm.gif' }, - // { post: 'https://anilist.co/activity/620600819', image: 'https://i.imgur.com/nHREaUc.png' }, - // { post: 'https://anilist.co/activity/620989269', image: 'https://imgur.com/XjhyOHU.png' }, - // { - // post: 'https://anilist.co/activity/621253410', - // image: - // 'https://cdn.discordapp.com/attachments/1139717993845239849/1147701375707381760/0028HLA.png' - // }, - // { post: 'https://anilist.co/activity/621787546', image: 'https://i.imgur.com/tn5yVsk.gif' }, - // { - // post: 'https://anilist.co/activity/621789551', - // image: 'https://i.postimg.cc/Z5325GDx/ota-day-otaku-academia-ittle-witch-academia.png' - // }, - // { post: 'https://anilist.co/activity/622236894', image: 'https://i.imgur.com/vicrIfS.png' }, - // { post: 'https://anilist.co/activity/622237728', image: 'https://i.imgur.com/TLSC65A.jpg' }, - // { post: 'https://anilist.co/activity/623156563', image: 'https://files.catbox.moe/ujf0ym.png' }, - // { post: 'https://anilist.co/activity/623990926', image: 'https://files.catbox.moe/gkalwm.png' }, - // { - // post: 'https://anilist.co/activity/623995806', - // image: - // 'https://cdn.discordapp.com/attachments/1118627570074800264/1154888665638649916/monikabday.png' - // }, - // { post: 'https://anilist.co/activity/624542383', image: 'https://files.catbox.moe/9tzs66.png' }, - // { - // post: 'https://anilist.co/activity/624542383', - // image: - // 'https://cdn.discordapp.com/attachments/1136989514653519924/1154540564671377459/EMILIA_BADGE_2.png' - // }, - // { post: 'https://anilist.co/activity/624543474', image: 'https://imgur.com/WQuXh6g.png' }, - // { - // post: 'https://anilist.co/activity/624544489', - // image: - // 'https://cdn.discordapp.com/attachments/1136989514653519924/1154736156093726870/fsdfwefewfwf.png' - // }, - // { - // post: 'https://anilist.co/activity/624545233', - // image: - // 'https://cdn.discordapp.com/attachments/1136989514653519924/1153606849464111134/katoubadge1.png' - // }, - // { post: 'https://anilist.co/activity/624548754', image: 'https://imgur.com/j5aqX5w.png' }, - // { - // post: 'https://anilist.co/activity/624549956', - // image: - // 'https://cdn.discordapp.com/attachments/1152962059126972417/1154745849465811015/Day_of_Mid_2.png' - // }, - // { post: 'https://anilist.co/activity/626483669', image: 'https://files.catbox.moe/lz0r48.png' }, - // { - // post: 'https://anilist.co/activity/626483669', - // image: - // 'https://cdn.discordapp.com/attachments/1118627570074800264/1156396779332456538/jojobdayb.png' - // }, - // { - // post: 'https://anilist.co/activity/626770819', - // image: - // 'https://cdn.discordapp.com/attachments/1136989514653519924/1156582649779994664/kikurihiroi.png' - // }, - // { post: 'https://anilist.co/activity/626772329', image: 'https://i.imgur.com/P09v438.gif' }, - // { - // post: 'https://anilist.co/activity/627283326', - // image: - // 'https://cdn.discordapp.com/attachments/1118627570074800264/1157124224197083226/coffeeday2.png' - // }, - // { - // post: 'https://anilist.co/activity/628202238', - // image: - // 'https://cdn.discordapp.com/attachments/1136989514653519924/1156472801457340506/rinshima1.png' - // }, - // { - // post: 'https://anilist.co/activity/628202913', - // image: - // 'https://cdn.discordapp.com/attachments/1136989514653519924/1157574135069806592/Badge-1_-_01_10_23.png' - // }, - // { - // post: 'https://anilist.co/activity/628305048', - // image: - // 'https://cdn.discordapp.com/attachments/1118627570074800264/1157650582094479370/SakeDay2.png' - // }, - // { post: 'https://anilist.co/activity/629168789', image: 'https://files.catbox.moe/0mwudd.png' }, - // { post: 'https://anilist.co/activity/629592629', image: 'https://files.catbox.moe/pyjy0z.png' }, - // { post: 'https://anilist.co/activity/629593251', image: 'https://files.catbox.moe/e9xx50.png' }, - // { post: 'https://anilist.co/activity/630084060', image: 'https://i.imgur.com/zVU0gie.gif' }, - // { post: 'https://anilist.co/activity/630462423', image: 'https://files.catbox.moe/b63wxi.png' }, - // { - // post: 'https://anilist.co/activity/630464366', - // image: - // 'https://cdn.discordapp.com/attachments/1118627570074800264/1158527481486266490/codegeass1.png' - // }, - // { post: 'https://anilist.co/activity/630996180', image: 'https://files.catbox.moe/ap15dx.png' }, - // { post: 'https://anilist.co/activity/631494022', image: 'https://files.catbox.moe/fw4rqx.png' }, - // { - // post: 'https://anilist.co/activity/631503062', - // image: - // 'https://cdn.discordapp.com/attachments/1118627570074800264/1158787682231660684/rize1.png' - // }, - // { - // post: 'https://anilist.co/activity/632259051', - // image: - // 'https://cdn.discordapp.com/attachments/1154438205731524638/1158943217459412992/Luna_Bday2023_Axel5.png' - // }, - // { post: 'https://anilist.co/activity/632260829', image: 'https://files.catbox.moe/ighico.png' }, - // { post: 'https://anilist.co/activity/632311940', image: 'https://files.catbox.moe/ukv6tv.png' }, - // { - // post: 'https://anilist.co/activity/632311940', - // image: - // 'https://cdn.discordapp.com/attachments/1136989514653519924/1160915207711895593/Gintoki_2.png' - // }, - // { - // post: 'https://anilist.co/activity/632407688', - // image: - // 'https://cdn.discordapp.com/attachments/1136989514653519924/1159856849735127110/Nishinoya_1.png' - // }, - // { post: 'https://anilist.co/activity/632832412', image: 'https://files.catbox.moe/9lk6s1.png' }, - // { post: 'https://anilist.co/activity/633710355', image: 'https://i.imgur.com/JmpriDr.gif' }, - // { post: 'https://anilist.co/activity/633710743', image: 'https://files.catbox.moe/it9d7q.png' }, - // { - // post: 'https://anilist.co/activity/633711260', - // image: - // 'https://cdn.discordapp.com/attachments/1118627570074800264/1160674827670134804/Sonia1.png' - // }, - // { post: 'https://anilist.co/activity/634118108', image: 'https://files.catbox.moe/tzudpj.png' }, - // { - // post: 'https://anilist.co/activity/634119722', - // image: - // 'https://cdn.discordapp.com/attachments/1085425937933418578/1162583650840354846/Mystery_Day_badge_4.png' - // } - // ]; - onMount(async () => { - // await fetch(`/api/badges/add`, { - // method: 'POST', - // body: JSON.stringify(badges) - // }); - if (data.user) { currentUserIdentity = userIdentity(data.user); } else { -- cgit v1.2.3 From dc9755d709b5bc88fd81f6e11641c1e78659283d Mon Sep 17 00:00:00 2001 From: Fuwn Date: Tue, 24 Oct 2023 17:28:39 -0700 Subject: fix(database): change path for docker --- src/lib/userBadgesDatabase.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/lib/userBadgesDatabase.ts b/src/lib/userBadgesDatabase.ts index ae1b1176..78655cd3 100644 --- a/src/lib/userBadgesDatabase.ts +++ b/src/lib/userBadgesDatabase.ts @@ -8,7 +8,7 @@ export interface Badge { id?: number; } -const database = new Database('./due_moe.sqlite3', { +const database = new Database('./data/due_moe.sqlite3', { verbose: dev ? console.log : undefined }); -- cgit v1.2.3 From 36d2b84670a096550b03ceb276184ab309b5364a Mon Sep 17 00:00:00 2001 From: Fuwn Date: Tue, 24 Oct 2023 18:09:27 -0700 Subject: feat(layout): profile item navigation --- src/routes/+layout.svelte | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/routes/+layout.svelte b/src/routes/+layout.svelte index 19df3f1c..20ae9ef4 100644 --- a/src/routes/+layout.svelte +++ b/src/routes/+layout.svelte @@ -52,11 +52,17 @@

HomeCompletedManga & LN Updates • - ToolsSettings 」 + Tools • {#if data.user} + Profile • + {/if} Settings

- HomeCompletedTools
+ HomeCompletedTools + {#if data.user} + • Profile + {/if} +
Settings Manga & LN Updates -- cgit v1.2.3 From 4a97d2608aaae9ff7711acf8f37ef45cdb349293 Mon Sep 17 00:00:00 2001 From: Fuwn Date: Tue, 24 Oct 2023 18:13:12 -0700 Subject: fix(routes): remove old user route --- src/routes/@[user]/+page.server.ts | 5 ----- src/routes/@[user]/+page.svelte | 45 -------------------------------------- 2 files changed, 50 deletions(-) delete mode 100644 src/routes/@[user]/+page.server.ts delete mode 100644 src/routes/@[user]/+page.svelte (limited to 'src') diff --git a/src/routes/@[user]/+page.server.ts b/src/routes/@[user]/+page.server.ts deleted file mode 100644 index 76d2d889..00000000 --- a/src/routes/@[user]/+page.server.ts +++ /dev/null @@ -1,5 +0,0 @@ -export const load = ({ params }) => { - return { - username: params.user - }; -}; diff --git a/src/routes/@[user]/+page.svelte b/src/routes/@[user]/+page.svelte deleted file mode 100644 index 1763193a..00000000 --- a/src/routes/@[user]/+page.svelte +++ /dev/null @@ -1,45 +0,0 @@ - - -{#if userData === null} - Could not load user profile for @{data.username}. - -

- - Does this user exist? -{:else if userData === undefined} - Loading ... -{:else} - @{userData.name} - -

- - This user has watched {(userData.statistics.anime.minutesWatched / 60 / 24).toFixed(1)} days of anime - and read - {((userData.statistics.manga.chaptersRead * 8.58) / 60 / 24).toFixed(1)} days of manga. -{/if} - -

- -


- -This page is under construction! -- cgit v1.2.3 From f99fd41ee23d7669812ff1d88d23a9b7f22db901 Mon Sep 17 00:00:00 2001 From: Fuwn Date: Tue, 24 Oct 2023 18:18:37 -0700 Subject: feat(user): prettier user route --- src/lib/AniList/user.ts | 5 ++++- src/routes/user/[user]/+page.svelte | 44 ++++++++++++++++++++++++++++--------- 2 files changed, 38 insertions(+), 11 deletions(-) (limited to 'src') diff --git a/src/lib/AniList/user.ts b/src/lib/AniList/user.ts index dd9995fd..fdc98a58 100644 --- a/src/lib/AniList/user.ts +++ b/src/lib/AniList/user.ts @@ -15,6 +15,9 @@ export interface User { volumesRead: number; }; }; + avatar: { + large: string; + }; } export const user = async (username: string): Promise => { @@ -28,7 +31,7 @@ export const user = async (username: string): Promise => { }, body: JSON.stringify({ query: `{ User(name: "${username}") { - name id statistics { + name id avatar { large } statistics { anime { count meanScore minutesWatched episodesWatched } diff --git a/src/routes/user/[user]/+page.svelte b/src/routes/user/[user]/+page.svelte index 227ba252..858e6aec 100644 --- a/src/routes/user/[user]/+page.svelte +++ b/src/routes/user/[user]/+page.svelte @@ -27,14 +27,38 @@ {:else if userData === undefined} Loading ... {:else} -

- @{userData.name} - • Badge Wall -

- - This user has watched {(userData.statistics.anime.minutesWatched / 60 / 24).toFixed(1)} days of anime - and read - {((userData.statistics.manga.chaptersRead * 8.58) / 60 / 24).toFixed(1)} days of manga. +
+

+ + + +

+ +
+

+ @{userData.name} + • Badge Wall +

+ + This user has watched {(userData.statistics.anime.minutesWatched / 60 / 24).toFixed(1)} days of + anime and read + {((userData.statistics.manga.chaptersRead * 8.58) / 60 / 24).toFixed(1)} days of manga. +
+
{/if} + + -- cgit v1.2.3 From e61da1367da23c309bd006416d598d861dfcfb2c Mon Sep 17 00:00:00 2001 From: Fuwn Date: Thu, 26 Oct 2023 14:48:00 -0700 Subject: refactor(badges): move to bun:sqlite --- src/lib/userBadgesDatabase.ts | 61 ++++++++++++++---------------- src/routes/api/badges/add/+server.ts | 11 ++++-- src/routes/user/[user]/badges/+page.svelte | 31 +++++++-------- 3 files changed, 52 insertions(+), 51 deletions(-) (limited to 'src') diff --git a/src/lib/userBadgesDatabase.ts b/src/lib/userBadgesDatabase.ts index 78655cd3..8cf40d5b 100644 --- a/src/lib/userBadgesDatabase.ts +++ b/src/lib/userBadgesDatabase.ts @@ -1,57 +1,54 @@ -import { dev } from '$app/environment'; -import Database from 'better-sqlite3'; +import { Database } from 'bun:sqlite'; export interface Badge { - post: string; - image: string; + post?: string; + image?: string; description?: string; id?: number; } const database = new Database('./data/due_moe.sqlite3', { - verbose: dev ? console.log : undefined + create: true }); -database.exec(`create table if not exists user_badges ( - id integer primary key, - user_id integer not null, - post text(1000) not null, - image text(1000) not null, - description text(1000) default null, - time timestamp default current_timestamp -)`); +database + .query( + `CREATE TABLE IF NOT EXISTS user_badges ( + id INTEGER PRIMARY KEY, + user_id INTEGER NOT NULL, + post TEXT(1000) NOT NULL, + image TEXT(1000) NOT NULL, + description TEXT(1000) DEFAULT NULL, + time TIMESTAMP DEFAULT CURRENT_TIMESTAMP +)` + ) + .run(); export const getUserBadges = (userId: number): Badge[] => { return database - .prepare('select * from user_badges where user_id = ?') - .all(String(userId)) as Badge[]; + .query('SELECT * FROM user_badges WHERE user_id = $userId') + .all({ $userId: String(userId) }) as Badge[]; }; export const addUserBadge = (userId: number, badge: Badge) => { const { post, image, description } = badge; - const statement = database.prepare(` - insert into user_badges (user_id, post, image, description) values (?, ?, ?, ?) - `); - statement.run(userId, post, image, description); -}; - -export const addUserBadges = (userId: number, badges: Badge[]) => { - const statement = database.prepare(` - insert into user_badges (user_id, post, image, description) values (?, ?, ?, ?) - `); + if (post === undefined || image === undefined) { + return; + } - for (const badge of badges) { - const { post, image, description } = badge; + const statement = database.query( + `INSERT INTO user_badges (user_id, post, image, description) VALUES (?1, ?2, ?3, ?4);` + ); - statement.run(userId, post, image, description); - } + statement.run([userId, post, image, description]); }; export const removeUserBadge = (userId: number, id: number) => { if (!isNaN(id)) { - const statement = database.prepare('delete from user_badges where user_id = ? and id = ?'); - - statement.run(userId, id); + database.query('DELETE FROM user_badges WHERE user_id = $userId AND id = $id').run({ + $userId: userId, + $id: id + }); } }; diff --git a/src/routes/api/badges/add/+server.ts b/src/routes/api/badges/add/+server.ts index 6ce9421e..627176a7 100644 --- a/src/routes/api/badges/add/+server.ts +++ b/src/routes/api/badges/add/+server.ts @@ -1,7 +1,7 @@ import { userIdentity } from '$lib/AniList/identity.js'; -import { addUserBadges } from '$lib/userBadgesDatabase.js'; +import { addUserBadge } from '$lib/userBadgesDatabase.js'; -export const POST = async ({ cookies, request }) => { +export const POST = async ({ cookies, url }) => { const userCookie = cookies.get('user'); if (!userCookie) { @@ -15,9 +15,12 @@ export const POST = async ({ cookies, request }) => { accessToken: user['access_token'], refreshToken: user['refresh_token'] }); - const formData = await request.json(); - addUserBadges(identity.id, formData); + addUserBadge(identity.id, { + post: url.searchParams.get('post') || undefined, + image: url.searchParams.get('image') || undefined, + description: url.searchParams.get('description') || undefined + }); return Response.json({}); }; diff --git a/src/routes/user/[user]/badges/+page.svelte b/src/routes/user/[user]/badges/+page.svelte index 293a7ba5..324d568e 100644 --- a/src/routes/user/[user]/badges/+page.svelte +++ b/src/routes/user/[user]/badges/+page.svelte @@ -26,25 +26,26 @@ const activityURL = document.querySelector('input[name="activity_url"]') as HTMLInputElement; const description = document.querySelector('input[name="description"]') as HTMLInputElement; - fetch(`/api/badges/add`, { - method: 'POST', - body: JSON.stringify([ - { image: imageURL.value, post: activityURL.value, description: description.value } - ]) + fetch( + `/api/badges/add?image=${encodeURIComponent(imageURL.value)}&post=${encodeURIComponent( + activityURL.value + )}&description=${encodeURIComponent(description.value)}`, + { + method: 'POST' + } + ).then(() => { + imageURL.value = ''; + activityURL.value = ''; + description.value = ''; }); - - console.log(imageURL.value, activityURL.value, description.value); - - imageURL.value = ''; - activityURL.value = ''; - description.value = ''; }; const removeBadge = (badge: Badge) => { fetch(`/api/badges/remove?id=${badge.id}`, { method: 'POST' + }).then(() => { + (document.querySelector(`#badge-${badge.id}`) as HTMLAnchorElement).style.display = 'none'; }); - (document.querySelector(`#badge-${badge.id}`) as HTMLAnchorElement).style.display = 'none'; }; @@ -56,9 +57,9 @@ Back to Profile {#if isOwner} • - (editMode = !editMode)} - >{editMode ? 'Disable' : 'Enable'} Edit Mode + (editMode = !editMode)}> + {editMode ? 'Disable' : 'Enable'} Edit Mode + {/if}

-- cgit v1.2.3