diff --git a/.gitignore b/.gitignore index b12bf67..34811c7 100644 --- a/.gitignore +++ b/.gitignore @@ -6,4 +6,5 @@ package-lock.json .env .env.local .vscode +.vercel .prisma \ No newline at end of file diff --git a/README.md b/README.md index f3c24b2..a84069d 100644 --- a/README.md +++ b/README.md @@ -5,7 +5,7 @@ # 🚩 **RevBots:- Rev Revolt Bots...** > RevBots is a Revolt bot list website that allows users to showcase their Revolt bots. This repository contains the code for both the ` RevBots ` website and the ` RevBot ` Discord bot. -⚠️ **Website Currently Using Non-Production Database** +⚠️ **Website Currently Using Non-Production Vercel Storage Database** --- --- @@ -26,7 +26,7 @@ Welcome to RevBots, a Revolt bot list website showcasing a collection of powerfu - Explore detailed bot profiles with descriptions, owner, socials etc. - Easily add bots to your Revolt server with just a click - Add your own bot easily -- Safe authentication system with Revolt API +- Authentication system with Revolt API - Better and Modern UI - Easy to explore and search @@ -82,9 +82,6 @@ Visit the [Live Preview](https://rev-bots-tau.vercel.app) to explore RevBots and ## 🧮 License RevBots and RevBot are both licensed under the ISC License. See the [LICENSE](LICENSE) file for more details. -## ⚡ Version -Latest version for **"RevBots"** repo is **` v0.1.1 `** - > _💫 Feel free to explore, contribute, and enjoy the world of RevBots and RevBot! And don't forget to give a star to this repo..._ --- diff --git a/bot/package.json b/bot/package.json index 187ff13..e85627e 100644 --- a/bot/package.json +++ b/bot/package.json @@ -1,6 +1,6 @@ { "name": "revbots-bot", - "version": "0.1.1", + "version": "0.1.3", "description": "Bot for Rev Bots Site!", "main": "index.js", "scripts": { diff --git a/package.json b/package.json index c48bb51..ffb1c6b 100644 --- a/package.json +++ b/package.json @@ -1,128 +1,7 @@ { "name": "revbots", - "version": "0.1.1", + "version": "0.1.3", "description": "Mono repo of RevBot's Bot and Website", - "dependencies": { - "acorn": "^8.8.2", - "acorn-jsx": "^5.3.2", - "astring": "^1.8.4", - "bail": "^2.0.2", - "busboy": "^1.6.0", - "ccount": "^2.0.1", - "character-entities": "^2.0.2", - "character-entities-html4": "^2.1.0", - "character-entities-legacy": "^3.0.0", - "character-reference-invalid": "^2.0.1", - "comma-separated-tokens": "^2.0.3", - "debug": "^4.3.4", - "decode-named-character-reference": "^1.0.2", - "dequal": "^2.0.3", - "diff": "^5.1.0", - "esbuild": "^0.17.18", - "estree-util-attach-comments": "^2.1.1", - "estree-util-build-jsx": "^2.2.2", - "estree-util-is-identifier-name": "^2.1.0", - "estree-util-to-js": "^1.2.0", - "estree-util-visit": "^1.2.1", - "estree-walker": "^3.0.3", - "extend": "^3.0.2", - "globrex": "^0.1.2", - "hast-util-to-estree": "^2.3.2", - "hast-util-whitespace": "^2.0.1", - "inline-style-parser": "^0.1.1", - "is-alphabetical": "^2.0.1", - "is-alphanumerical": "^2.0.1", - "is-buffer": "^2.0.5", - "is-decimal": "^2.0.1", - "is-hexadecimal": "^2.0.1", - "is-plain-obj": "^4.1.0", - "is-reference": "^3.0.1", - "kleur": "^4.1.5", - "longest-streak": "^3.1.0", - "markdown-extensions": "^1.1.1", - "mdast-util-definitions": "^5.1.2", - "mdast-util-from-markdown": "^1.3.0", - "mdast-util-mdx": "^2.0.1", - "mdast-util-mdx-expression": "^1.3.2", - "mdast-util-mdx-jsx": "^2.1.2", - "mdast-util-mdxjs-esm": "^1.3.1", - "mdast-util-phrasing": "^3.0.1", - "mdast-util-to-hast": "^12.3.0", - "mdast-util-to-markdown": "^1.5.0", - "mdast-util-to-string": "^3.2.0", - "micromark": "^3.1.0", - "micromark-core-commonmark": "^1.0.6", - "micromark-extension-mdx-expression": "^1.0.4", - "micromark-extension-mdx-jsx": "^1.0.3", - "micromark-extension-mdx-md": "^1.0.1", - "micromark-extension-mdxjs": "^1.0.0", - "micromark-extension-mdxjs-esm": "^1.0.3", - "micromark-factory-destination": "^1.0.0", - "micromark-factory-label": "^1.0.2", - "micromark-factory-mdx-expression": "^1.0.7", - "micromark-factory-space": "^1.0.0", - "micromark-factory-title": "^1.0.2", - "micromark-factory-whitespace": "^1.0.0", - "micromark-util-character": "^1.1.0", - "micromark-util-chunked": "^1.0.0", - "micromark-util-classify-character": "^1.0.0", - "micromark-util-combine-extensions": "^1.0.0", - "micromark-util-decode-numeric-character-reference": "^1.0.0", - "micromark-util-decode-string": "^1.0.2", - "micromark-util-encode": "^1.0.1", - "micromark-util-events-to-acorn": "^1.2.1", - "micromark-util-html-tag-name": "^1.1.0", - "micromark-util-normalize-identifier": "^1.0.0", - "micromark-util-resolve-all": "^1.0.0", - "micromark-util-sanitize-uri": "^1.1.0", - "micromark-util-subtokenize": "^1.0.2", - "micromark-util-symbol": "^1.0.1", - "micromark-util-types": "^1.0.2", - "mri": "^1.2.0", - "ms": "^2.1.2", - "nanoid": "^3.3.6", - "node-bin-setup": "^1.1.3", - "parse-entities": "^4.0.1", - "periscopic": "^3.1.0", - "picocolors": "^1.0.0", - "postcss": "^8.4.23", - "property-information": "^6.2.0", - "remark-mdx": "^2.3.0", - "remark-parse": "^10.0.1", - "remark-rehype": "^10.1.0", - "rollup": "^3.21.6", - "sade": "^1.8.1", - "source-map": "^0.7.4", - "source-map-js": "^1.0.2", - "space-separated-tokens": "^2.0.2", - "streamsearch": "^1.1.0", - "stringify-entities": "^4.0.3", - "style-to-object": "^0.4.1", - "trim-lines": "^3.0.1", - "trough": "^2.1.0", - "tsconfck": "^2.1.1", - "undici": "^5.22.1", - "unified": "^10.1.2", - "unist-util-generated": "^2.0.1", - "unist-util-is": "^5.2.1", - "unist-util-position": "^4.0.4", - "unist-util-position-from-estree": "^1.1.2", - "unist-util-remove-position": "^4.0.2", - "unist-util-stringify-position": "^3.0.3", - "unist-util-visit": "^4.1.2", - "unist-util-visit-parents": "^5.1.3", - "uvu": "^0.5.6", - "vfile": "^5.3.7", - "vfile-location": "^4.1.0", - "vfile-message": "^3.1.4", - "vite": "^4.3.5", - "vite-tsconfig-paths": "^4.2.0", - "zod": "^3.21.4", - "zwitch": "^2.0.4" - }, - "devDependencies": { - "node": "^20.2.0" - }, "repository": { "type": "git", "url": "git+https://github.com/ArnavK-09/RevBots.git" @@ -132,7 +11,5 @@ "bugs": { "url": "https://github.com/ArnavK-09/RevBots/issues" }, - "homepage": "https://github.com/ArnavK-09/RevBots#readme", - "main": "index.js", - "keywords": [] + "homepage": "https://github.com/ArnavK-09/RevBots#readme" } diff --git a/website/package.json b/website/package.json index 2fec6e1..cdba4d1 100644 --- a/website/package.json +++ b/website/package.json @@ -1,6 +1,6 @@ { "name": "revbots-site", - "version": "0.1.1", + "version": "0.1.3", "description": "Website for Rev Bots!", "author": "ArnavK-09", "license": "ISC", @@ -18,8 +18,9 @@ "@iconify/svelte": "^3.1.3", "@sveltejs/adapter-auto": "^2.0.0", "@sveltejs/adapter-vercel": "^3.0.0", - "@sveltejs/kit": "^1.5.0", + "@sveltejs/kit": "^1.20.3", "@types/crypto-js": "^4.1.1", + "@types/ms": "^0.7.31", "@types/showdown": "^2.0.1", "@typescript-eslint/eslint-plugin": "^5.45.0", "@typescript-eslint/parser": "^5.45.0", @@ -42,10 +43,12 @@ "dependencies": { "@prisma/client": "^4.15.0", "@tailwindcss/forms": "^0.5.3", - "@types/node": "^20.2.5", + "@types/node": "^20.3.1", "axios": "^1.4.0", "crypto-js": "^4.1.1", - "dotenv": "^16.0.3", - "showdown": "^2.1.0" + "dotenv": "^16.3.0", + "ms": "^2.1.3", + "showdown": "^2.1.0", + "tiny-glob": "^0.2.9" } } diff --git a/website/prisma/schema.prisma b/website/prisma/schema.prisma index e8ac460..7d478f8 100644 --- a/website/prisma/schema.prisma +++ b/website/prisma/schema.prisma @@ -1,6 +1,4 @@ -// This is your Prisma schema file, -// learn more about it in the docs: https://pris.ly/d/prisma-schema - +// Base Prisma generator client { provider = "prisma-client-js" previewFeatures = ["fullTextSearch"] @@ -11,14 +9,17 @@ datasource db { url = env("DB_URL") } +// Models model User { - id String @id @default(uuid()) @db.Uuid - username String @unique - identifier String @unique - avatar String @default("/logo.png") - verified Boolean @default(false) - createdAt DateTime @default(now()) - bots Bot[] + id String @id @default(uuid()) @db.Uuid + username String + discriminator String + identifier String @unique + avatar String @default("/logo.png") + verified Boolean @default(false) + createdAt DateTime @default(now()) + bots Bot[] + vote_timers Vote[] } model Bot { @@ -34,14 +35,34 @@ model Bot { support String? github String invite String - username String @unique + username String identifier String @unique + discriminator String publishedOn DateTime @default(now()) prefix String status BotStatus @default(PENDING) promoted Boolean @default(false) + active_votes Vote[] +} + +model Request { + code String @id @unique @default("CODE") + status Boolean @default(false) + user String @unique +} + +model Vote { + voter User @relation(fields: [voterIdentifier], references: [identifier], onDelete: Cascade) + voterIdentifier String + bot Bot @relation(fields: [botIdentifier], references: [identifier], onDelete: Cascade) + botIdentifier String + key String @unique @default(uuid()) @db.Uuid + time DateTime @default(now()) + + @@unique([botIdentifier, voterIdentifier]) } +// Enums enum Tag { ANIME FUN @@ -61,9 +82,3 @@ enum BotStatus { DEPRECATED PENDING } - -model Request { - code String @id @unique @default("CODE") - status Boolean @default(false) - user String @unique -} diff --git a/website/src/app.html b/website/src/app.html index 8f09dd7..3423abd 100644 --- a/website/src/app.html +++ b/website/src/app.html @@ -3,6 +3,7 @@ + %sveltekit.head% diff --git a/website/src/global.css b/website/src/global.css index 9f1f5cd..5a4d439 100644 --- a/website/src/global.css +++ b/website/src/global.css @@ -14,7 +14,7 @@ body { /* no scroll bar */ @layer utilities { - @variants responsive { + @layer components { /* Hide scrollbar for Chrome, Safari and Opera */ .no-scrollbar::-webkit-scrollbar { display: none; diff --git a/website/src/lib/components/Botpage/Header.svelte b/website/src/lib/components/Botpage/Header.svelte index cac88ca..397bc08 100644 --- a/website/src/lib/components/Botpage/Header.svelte +++ b/website/src/lib/components/Botpage/Header.svelte @@ -4,9 +4,10 @@ // props export let name = 'Revolt Name'; - export let description = 'Bot Description'; + export let description = 'No Bot Description Provided...'; export let id = 0; export let avatar = '/favicon.png'; + export let actions = true;
@@ -22,7 +23,7 @@

{name}

Server ID: #{id} {#if description}

{description}

{/if} - + {#if actions}{/if}
diff --git a/website/src/lib/components/Botpage/Info.svelte b/website/src/lib/components/Botpage/Info.svelte index c463b35..115982d 100644 --- a/website/src/lib/components/Botpage/Info.svelte +++ b/website/src/lib/components/Botpage/Info.svelte @@ -25,6 +25,10 @@ name: 'Identifier', value: data.identifier }, + { + name: 'Discriminator', + value: `#${data.discriminator}` + }, { name: 'Prefix', value: data.prefix diff --git a/website/src/lib/components/Botpage/Owner.svelte b/website/src/lib/components/Botpage/Owner.svelte index 6f36f53..82b7d13 100644 --- a/website/src/lib/components/Botpage/Owner.svelte +++ b/website/src/lib/components/Botpage/Owner.svelte @@ -12,7 +12,7 @@ src={avatar} alt="Owner PFP" /> -
+
Owned By:@{name}
diff --git a/website/src/lib/components/Cards/Bot.svelte b/website/src/lib/components/Cards/Bot.svelte index d7e6c25..bd34c47 100644 --- a/website/src/lib/components/Cards/Bot.svelte +++ b/website/src/lib/components/Cards/Bot.svelte @@ -5,6 +5,7 @@ // props export let id: string; + export let username: string; export let votes = 0; export let description: string | null; export let avatar = '/logo.png'; @@ -17,14 +18,14 @@
- + {`${id}
- +

- {id} + {username}

@@ -44,18 +45,22 @@ {/each}

diff --git a/website/src/lib/components/Cards/PromotedBot.svelte b/website/src/lib/components/Cards/PromotedBot.svelte index 54fd7fe..fcb0f4b 100644 --- a/website/src/lib/components/Cards/PromotedBot.svelte +++ b/website/src/lib/components/Cards/PromotedBot.svelte @@ -3,6 +3,7 @@ import Icon from '@iconify/svelte'; // props export let id: string; + export let username: string; export let description: string | null; export let avatar = '/logo.png'; @@ -13,18 +14,18 @@
@@ -33,7 +34,7 @@ {description ?? 'No Description Available...'}

diff --git a/website/src/lib/components/Explore/Bots.svelte b/website/src/lib/components/Explore/Bots.svelte index 7f662ef..ba63a3b 100644 --- a/website/src/lib/components/Explore/Bots.svelte +++ b/website/src/lib/components/Explore/Bots.svelte @@ -1,7 +1,7 @@ -
diff --git a/website/src/routes/admin@[pass]/+layout.svelte b/website/src/routes/(backend)/admin@[pass]/+layout.svelte similarity index 100% rename from website/src/routes/admin@[pass]/+layout.svelte rename to website/src/routes/(backend)/admin@[pass]/+layout.svelte diff --git a/website/src/routes/admin@[pass]/+page.server.ts b/website/src/routes/(backend)/admin@[pass]/+page.server.ts similarity index 86% rename from website/src/routes/admin@[pass]/+page.server.ts rename to website/src/routes/(backend)/admin@[pass]/+page.server.ts index 7ed83cf..1a6cb34 100644 --- a/website/src/routes/admin@[pass]/+page.server.ts +++ b/website/src/routes/(backend)/admin@[pass]/+page.server.ts @@ -1,8 +1,9 @@ // imports -import type { PageServerLoad, Actions } from './$types'; +import type { PageServerLoad, Actions, RequestEvent } from './$types'; import { redirect, error, fail } from '@sveltejs/kit'; import DB from '$lib/server/database'; import { env } from '$env/dynamic/private'; +import type { BotStatus } from '@prisma/client'; // load search export const load = (async ({ params }) => { @@ -24,10 +25,10 @@ export const load = (async ({ params }) => { // actions export const actions = { - status: async ({ request }: any) => { + status: async ({ request }: RequestEvent) => { const data = await request.formData(); - const bot = data.get('identifier'); - const status = data.get('status'); + const bot = data.get('identifier') as string; + const status = data.get('status') as BotStatus; // update status await DB.bot .update({ diff --git a/website/src/routes/admin@[pass]/+page.svelte b/website/src/routes/(backend)/admin@[pass]/+page.svelte similarity index 95% rename from website/src/routes/admin@[pass]/+page.svelte rename to website/src/routes/(backend)/admin@[pass]/+page.svelte index 63299ac..001e799 100644 --- a/website/src/routes/admin@[pass]/+page.svelte +++ b/website/src/routes/(backend)/admin@[pass]/+page.svelte @@ -34,7 +34,7 @@ />
-

{bot.username}

+

{bot.username}#{bot.discriminator}

Server ID: #{bot.id}
@@ -46,7 +46,7 @@ Short Description: {bot.shortDescription ?? 'No Short Description'}

-

+

{bot.description}

diff --git a/website/src/routes/api/+server.ts b/website/src/routes/(backend)/api/+server.ts similarity index 95% rename from website/src/routes/api/+server.ts rename to website/src/routes/(backend)/api/+server.ts index ac48a6d..2522e2c 100644 --- a/website/src/routes/api/+server.ts +++ b/website/src/routes/(backend)/api/+server.ts @@ -2,7 +2,7 @@ import { json } from '@sveltejs/kit'; import type { RequestHandler } from './$types'; import os from 'os'; -import { version as appVersion } from '../../../package.json'; +import { version as appVersion } from '../../../../package.json'; import { version as svelteKitVersion } from '@sveltejs/kit/package.json'; import { version as prismaV } from '@prisma/client/package.json'; diff --git a/website/src/routes/api/auth/+server.ts b/website/src/routes/(backend)/api/auth/+server.ts similarity index 95% rename from website/src/routes/api/auth/+server.ts rename to website/src/routes/(backend)/api/auth/+server.ts index b367c2c..ada7835 100644 --- a/website/src/routes/api/auth/+server.ts +++ b/website/src/routes/(backend)/api/auth/+server.ts @@ -3,7 +3,7 @@ import { error, json, redirect } from '@sveltejs/kit'; import DB from '$lib/server/database'; import type { RequestHandler } from './$types'; import { encrypt } from '$lib/server/modules/JWA'; -import axios from 'axios'; +import axios, { type AxiosResponse } from 'axios'; import { env } from '$env/dynamic/private'; /* Helper functions*/ @@ -114,21 +114,21 @@ export const GET = async ({ url, cookies }: any) => { // if user not exist if (!user) { // fetch revolt user data - const revoltUserData: any = await axios + const revoltUserData: AxiosResponse = await axios .get(`https://api.revolt.chat/users/${requestOnDB.user}`, { headers: { 'X-Bot-Token': env.BOT_TOKEN } }) - .catch((e) => { - console.log(e, env.BOT_TOKEN); + .catch(() => { throw error(403, { message: 'Unable to fetch revolt profile' }); }); // create user const userData: any = { avatar: `https://autumn.revolt.chat/avatars/${revoltUserData.data.avatar._id}/${revoltUserData.data.avatar.filename}`, identifier: requestOnDB.user, - username: revoltUserData.data.username + username: revoltUserData.data.username, + discriminator: revoltUserData.data.discriminator }; const createdUser = await DB.user.create({ data: userData }).catch(() => { throw error(500, { message: 'Error in creating new user' }); diff --git a/website/src/routes/api/bots/+server.ts b/website/src/routes/(backend)/api/bots/+server.ts similarity index 100% rename from website/src/routes/api/bots/+server.ts rename to website/src/routes/(backend)/api/bots/+server.ts diff --git a/website/src/routes/api/bots/[id]/+server.ts b/website/src/routes/(backend)/api/bots/[id]/+server.ts similarity index 96% rename from website/src/routes/api/bots/[id]/+server.ts rename to website/src/routes/(backend)/api/bots/[id]/+server.ts index ad2e776..db6d3b7 100644 --- a/website/src/routes/api/bots/[id]/+server.ts +++ b/website/src/routes/(backend)/api/bots/[id]/+server.ts @@ -9,7 +9,7 @@ export const GET = (async ({ params }: any) => { const selectedBot = await DB.bot .findUnique({ where: { - username: params.id + identifier: params.id } }) .catch(() => { diff --git a/website/src/routes/(backend)/api/bots/[id]/vote/+server.ts b/website/src/routes/(backend)/api/bots/[id]/vote/+server.ts new file mode 100644 index 0000000..b8bcb67 --- /dev/null +++ b/website/src/routes/(backend)/api/bots/[id]/vote/+server.ts @@ -0,0 +1,68 @@ +// imports +import { json, error } from '@sveltejs/kit'; +import DB from '$lib/server/database'; +import type { RequestHandler } from './$types'; +import { decrypt } from '$lib/server/modules/JWA'; +import ms from 'ms'; + +// helper function +function userCanVote(vote: any) { + const result = 86400000 - (Date.now() - new Date(vote.time).getTime()); + const fmtRes = ms(result, { long: true }); + if (result <= 0 || fmtRes.includes('-')) + return { + status: true, + time_left: 'Time to vote now' + }; + return { + status: false, + time_left: fmtRes + }; +} + +// GET /api/bots/[id]/vote +export const GET = (async ({ params, cookies }: any) => { + // data + const botID = params.id; + const voterID: any = decrypt(cookies.get('revAuth')); + + // validate + if (!botID) { + throw error(400, { message: 'Missing Params' }); + } + // get user + const voter = await DB.user + .findUnique({ + where: { + id: voterID + } + }) + .catch(() => { + throw error(500, { message: 'Unable to contact database' }); + }); + if (!voter) { + throw error(401, { message: 'No user found' }); + } + // get pending req + const pendingRequest = await DB.vote + .findFirst({ + where: { + botIdentifier: botID, + voterIdentifier: voter.identifier + } + }) + .catch(() => { + throw error(500, { message: 'Unable to contact database' }); + }); + if (pendingRequest) { + return json({ vote: pendingRequest, can_vote: userCanVote(pendingRequest) }); + } + // if not pending req + return json({ + vote: null, + can_vote: { + status: true, + time_left: 'Time to vote now' + } + }); +}) satisfies RequestHandler; diff --git a/website/src/routes/api/me/+server.ts b/website/src/routes/(backend)/api/me/+server.ts similarity index 100% rename from website/src/routes/api/me/+server.ts rename to website/src/routes/(backend)/api/me/+server.ts diff --git a/website/src/routes/api/me/bots/+server.ts b/website/src/routes/(backend)/api/me/bots/+server.ts similarity index 84% rename from website/src/routes/api/me/bots/+server.ts rename to website/src/routes/(backend)/api/me/bots/+server.ts index 604c903..4001f6e 100644 --- a/website/src/routes/api/me/bots/+server.ts +++ b/website/src/routes/(backend)/api/me/bots/+server.ts @@ -3,7 +3,7 @@ import type { RequestHandler } from './$types'; import { json, error } from '@sveltejs/kit'; import DB from '$lib/server/database'; import { decrypt } from '$lib/server/modules/JWA'; -import axios from 'axios'; +import axios, { type AxiosResponse } from 'axios'; import { env } from '$env/dynamic/private'; // GET /api/me/bots @@ -12,7 +12,7 @@ export const GET = (async ({ cookies }) => { const auth: string | null = decrypt(cookies.get('revAuth')); // if if (!auth) { - throw error(401, { message: 'No auth?' }); + throw error(401, { message: 'No auth provided' }); } // get user bots @@ -49,24 +49,28 @@ export const POST = (async ({ request, cookies }) => { throw error(400, { message: 'Invalid Github Repo' }); } // check if bot exists - const botOnDB = await DB.bot.findUnique({ - where: { - identifier: data.identifier.trim().toUpperCase() - } - }); + const botOnDB = await DB.bot + .findUnique({ + where: { + identifier: data.identifier.trim().toUpperCase() + } + }) + .catch(() => { + throw error(500, { message: 'Unable to contact database' }); + }); if (botOnDB) { return json(botOnDB); } // fetch username - const bot = await axios + const bot: AxiosResponse = await axios .get(`https://api.revolt.chat/bots/${data.identifier.toString()}/invite`) .catch(() => { throw error(406, { message: 'Unable to fetch bot on revolt' }); }); // fetch revolt bot data - const revoltBotData = await axios + const revoltBotData: AxiosResponse = await axios .get(`https://api.revolt.chat/users/${data.identifier.toUpperCase()}`, { headers: { 'X-Bot-Token': env.BOT_TOKEN @@ -81,10 +85,10 @@ export const POST = (async ({ request, cookies }) => { if (revoltBotData.data.avatar) { avatar = `https://autumn.revolt.chat/avatars/${revoltBotData.data.avatar._id}/${revoltBotData.data.avatar.filename}`; } - // create bot - const botData = { + const botData: any = { username: bot.data.username, + discriminator: revoltBotData.data.discriminator, identifier: data.identifier, avatar: avatar, description: data.longDescription, @@ -102,8 +106,7 @@ export const POST = (async ({ request, cookies }) => { .create({ data: botData }) - .catch((err) => { - console.log(err); + .catch(() => { throw error(500, { message: 'Unable to create bot' }); }); diff --git a/website/src/routes/api/search/bots/+server.ts b/website/src/routes/(backend)/api/search/bots/+server.ts similarity index 100% rename from website/src/routes/api/search/bots/+server.ts rename to website/src/routes/(backend)/api/search/bots/+server.ts diff --git a/website/src/routes/api/tags/+server.ts b/website/src/routes/(backend)/api/tags/+server.ts similarity index 100% rename from website/src/routes/api/tags/+server.ts rename to website/src/routes/(backend)/api/tags/+server.ts diff --git a/website/src/routes/me/+layout.svelte b/website/src/routes/(frontend)/@me/+layout.svelte similarity index 100% rename from website/src/routes/me/+layout.svelte rename to website/src/routes/(frontend)/@me/+layout.svelte diff --git a/website/src/routes/me/+page.svelte b/website/src/routes/(frontend)/@me/+page.svelte similarity index 86% rename from website/src/routes/me/+page.svelte rename to website/src/routes/(frontend)/@me/+page.svelte index 730c5f3..8ca064e 100644 --- a/website/src/routes/me/+page.svelte +++ b/website/src/routes/(frontend)/@me/+page.svelte @@ -26,7 +26,7 @@ }); - +
- +
diff --git a/website/src/routes/@[botname]/invite/+page.server.ts b/website/src/routes/(frontend)/bot/[botid]/invite/+page.server.ts similarity index 92% rename from website/src/routes/@[botname]/invite/+page.server.ts rename to website/src/routes/(frontend)/bot/[botid]/invite/+page.server.ts index 7c57bc6..9571292 100644 --- a/website/src/routes/@[botname]/invite/+page.server.ts +++ b/website/src/routes/(frontend)/bot/[botid]/invite/+page.server.ts @@ -5,13 +5,13 @@ import DB from '$lib/server/database'; // redirect to invite link of bot export const load = (async ({ params }) => { - if (!params.botname) { + if (!params.botid) { throw error(400, { message: 'Bot Id Not Provided' }); } const botOnDB = await DB.bot .findUnique({ where: { - username: params.botname + identifier: params.botid }, select: { invite: true diff --git a/website/src/routes/(frontend)/bot/[botid]/vote/+page.server.ts b/website/src/routes/(frontend)/bot/[botid]/vote/+page.server.ts new file mode 100644 index 0000000..cecfb89 --- /dev/null +++ b/website/src/routes/(frontend)/bot/[botid]/vote/+page.server.ts @@ -0,0 +1,115 @@ +// imports +import type { PageServerLoad, Actions, RequestEvent } from './$types'; +import { error, fail, redirect } from '@sveltejs/kit'; +import DB from '$lib/server/database'; +import ms from 'ms'; +import type { User } from '@prisma/client'; + +// get bot data +export const load = (async ({ fetch, params }: any) => { + // values + const botId = params.botid; + + /* get bot */ + const req = await fetch(`/api/bots/${botId}`); + const data = await req.json(); + + // error check + if (!(req.status == 200)) { + throw error(404, { message: 'Bot Not Found' }); + } + + // send data + return { bot: data.bot }; +}) satisfies PageServerLoad; + +// vote actions +export const actions = { + default: async ({ request }: RequestEvent) => { + // get values + const form = await request.formData(); + const userID = form.get('user') as string; + const botID = form.get('bot') as string; + + // get user + const user = await DB.user + .findUnique({ + where: { + id: userID + } + }) + .catch(() => { + return fail(500, { success: false, error: 'Unable to contact database' }); + }); + if (!user) { + throw error(401, { message: 'Not auth?' }); + } + + // get vote req + const voteReq = await DB.vote + .findFirst({ + where: { + botIdentifier: botID, + voterIdentifier: (user as User).identifier + } + }) + .catch(() => { + return fail(500, { success: false, error: 'Unable to contact database' }); + }); + if (voteReq && !userCanVote(voteReq)) { + return fail(400, { message: 'You cannot vote now' }); + } + + // update bot + await DB.bot + .update({ + where: { + identifier: botID + }, + data: { + votes: { + increment: 1 + } + } + }) + .catch(() => { + return fail(500, { success: false, error: 'Unable to contact database' }); + }) + .then(async () => { + // update vote + await DB.vote.upsert({ + where: { + botIdentifier_voterIdentifier: { + botIdentifier: botID, + voterIdentifier: (user as User).identifier + } + }, + update: { + time: new Date() + }, + create: { + botIdentifier: botID, + voterIdentifier: (user as User).identifier + } + }); + }) + .finally(() => { + throw redirect(302, `/bot/${botID}?message=Voted Done`); + }); + } +} satisfies Actions; + +// helper function +function userCanVote(vote: any) { + const result = 86400000 - (Date.now() - new Date(vote.time).getTime()); + const fmtRes = ms(result, { long: true }); + if (result <= 0 || fmtRes.includes('-')) + return { + status: true, + time_left: 'Time to vote now' + }; + return { + status: false, + time_left: fmtRes + }; +} diff --git a/website/src/routes/(frontend)/bot/[botid]/vote/+page.svelte b/website/src/routes/(frontend)/bot/[botid]/vote/+page.svelte new file mode 100644 index 0000000..972ec46 --- /dev/null +++ b/website/src/routes/(frontend)/bot/[botid]/vote/+page.svelte @@ -0,0 +1,79 @@ + + + +
+ +
+ + {#if User.identifier} + {JSON.stringify(User)} +
+
+
+

+ Time Remaining to vote: {userVoteData.can_vote?.time_left ?? 'Loading'} +

+
+
+ + + + + +
+
+
+ {:else} +
+

+ You need to be logged in +

+
+ {/if} +
+
diff --git a/website/src/routes/search/+page.server.ts b/website/src/routes/(frontend)/search/+page.server.ts similarity index 100% rename from website/src/routes/search/+page.server.ts rename to website/src/routes/(frontend)/search/+page.server.ts diff --git a/website/src/routes/(frontend)/search/+page.svelte b/website/src/routes/(frontend)/search/+page.svelte new file mode 100644 index 0000000..7e0c497 --- /dev/null +++ b/website/src/routes/(frontend)/search/+page.svelte @@ -0,0 +1,32 @@ + + + + +{#if !(data.bots.length == 0)} + +{:else} +
+

No Bots Found :(

+
+{/if} diff --git a/website/src/routes/bot/+server.ts b/website/src/routes/(redirects)/bot/+server.ts similarity index 68% rename from website/src/routes/bot/+server.ts rename to website/src/routes/(redirects)/bot/+server.ts index d0f8db7..1941c99 100644 --- a/website/src/routes/bot/+server.ts +++ b/website/src/routes/(redirects)/bot/+server.ts @@ -4,5 +4,5 @@ import type { RequestHandler } from './$types'; // GET /discord export const GET = (() => { - throw redirect(301, '/@RevBots/invite'); + throw redirect(301, 'https://app.revolt.chat/bot/01H08716FW8WXP2RGH98S5VSXJ'); }) satisfies RequestHandler; diff --git a/website/src/routes/github/+server.ts b/website/src/routes/(redirects)/github/+server.ts similarity index 100% rename from website/src/routes/github/+server.ts rename to website/src/routes/(redirects)/github/+server.ts diff --git a/website/src/routes/support/+server.ts b/website/src/routes/(redirects)/support/+server.ts similarity index 100% rename from website/src/routes/support/+server.ts rename to website/src/routes/(redirects)/support/+server.ts diff --git a/website/src/routes/+layout.svelte b/website/src/routes/+layout.svelte index 9a3ad17..43ef073 100644 --- a/website/src/routes/+layout.svelte +++ b/website/src/routes/+layout.svelte @@ -12,6 +12,7 @@ // components import Navbar from '$lib/components/Navbar.svelte'; import Footer from '$lib/components/Footer.svelte'; + import Loader from '$lib/components/Loader.svelte'; import Icon from '@iconify/svelte'; // variables @@ -41,7 +42,7 @@ }> = [ { name: 'Home', url: '/' }, { name: 'Explore Bots', url: '/' }, - { name: 'Your Profile', url: '/me' }, + { name: 'Your Profile', url: '/@me' }, { name: 'Github', url: '/github' }, { name: 'Support', url: '/support' }, { name: 'API', url: '/api' } @@ -55,13 +56,18 @@ class="flex justify-center items-center z-40 p-auto h-screen w-screen bg-black/50 fixed left-0 top-0" >
- +
{/if} {#if $nav} -
+
console.log('Navbar key press')} + on:click={() => nav.set(false)} + transition:fade + class="z-20 h-screen w-screen bg-black/70 fixed top-0" + /> {/if} {#if $nav}