1
0
Fork 0

kaboom (nuke)

This commit is contained in:
Kim, Jimin 2022-12-22 00:13:30 +09:00
parent c67ac831d6
commit 0687831b92
47 changed files with 1 additions and 14358 deletions

View file

@ -1,56 +0,0 @@
name: Deploy frontend
on:
workflow_dispatch:
push:
paths:
- frontend/**
branches:
- master
jobs:
build:
name: Build
runs-on: ubuntu-latest
steps:
- name: Checkout Repo
uses: actions/checkout@master
- uses: actions/setup-node@v2
with:
node-version: 16
cache: npm
cache-dependency-path: frontend/package-lock.json
- name: Install Dependencies
run: npm --prefix frontend install
- name: Build
run: npm --prefix frontend run build
- name: Archive Production Artifact
uses: actions/upload-artifact@master
with:
name: frontend_build
path: frontend/build
deploy:
name: Deploy
needs: build
runs-on: ubuntu-latest
steps:
- name: Checkout Repo
uses: actions/checkout@master
- name: Download Artifact
uses: actions/download-artifact@master
with:
name: frontend_build
path: frontend/build
- name: Deploy to Firebase
uses: w9jds/firebase-action@master
with:
args: deploy --only hosting
env:
FIREBASE_TOKEN: ${{ secrets.FIREBASE_TOKEN }}
PROJECT_ID: ${{ secrets.FIREBASE_PROJECT }}

View file

@ -1,45 +0,0 @@
name: Deploy functions
on:
workflow_dispatch:
push:
paths:
- functions/**
branches:
- master
jobs:
build:
name: Build
runs-on: ubuntu-latest
steps:
- name: Checkout Repo
uses: actions/checkout@master
- uses: actions/setup-node@v2
with:
node-version: 16
cache: npm
cache-dependency-path: functions/package-lock.json
- name: Install Dependencies
run: npm --prefix functions install
- name: Restore secrets
run: |
echo $SECRET_JSON > ./functions/src/secret.json
echo $FIREBASE_ADMINSDK_JSON > ./functions/src/firebase-adminsdk.json
shell: bash
env:
SECRET_JSON: ${{ secrets.SECRET_JSON }}
FIREBASE_ADMINSDK_JSON: ${{ secrets.FIREBASE_ADMINSDK_JSON }}
- name: Build
run: npm --prefix functions run build
- name: Deploy to Firebase
uses: w9jds/firebase-action@master
with:
args: deploy --only functions
env:
FIREBASE_TOKEN: ${{ secrets.FIREBASE_TOKEN }}
PROJECT_ID: ${{ secrets.FIREBASE_PROJECT }}

6
.gitignore vendored
View file

@ -1,6 +0,0 @@
/_/
.firebase/
.firebaserc
firestore.indexes.json
*.log

View file

@ -1,4 +0,0 @@
{
"semi": false,
"useTabs": true
}

View file

@ -1,3 +0,0 @@
{
"recommendations": ["svelte.svelte-vscode", "esbenp.prettier-vscode"]
}

View file

@ -1,6 +0,0 @@
{
"editor.defaultFormatter": "esbenp.prettier-vscode",
"editor.formatOnPaste": true,
"editor.formatOnSave": true,
"cSpell.words": ["developomp", "firestore", "Sider"]
}

View file

@ -1 +0,0 @@
[Go here](https://github.com/llama-bot/llama-bot/blob/master/CONTRIBUTING.md)

19
LICENSE
View file

@ -1,19 +0,0 @@
Copyright (c) 2021 developomp
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE
OR OTHER DEALINGS IN THE SOFTWARE.

View file

@ -1,3 +1,3 @@
# llama-bot-web-interface
## [Documentation](https://llama-bot.github.io/llama-bot-docs/docs/web-interface/overview)
**This project is dead.**

View file

@ -1,37 +0,0 @@
{
"functions": {
"source": "functions"
},
"firestore": {
"rules": "firestore.rules",
"indexes": "firestore.indexes.json"
},
"hosting": {
"public": "frontend/build/",
"ignore": ["firebase.json", "**/.*", "**/node_modules/**"],
"rewrites": [
{
"source": "/api/**",
"function": "api"
},
{
"source": "**",
"destination": "/index.html"
}
]
},
"emulators": {
"functions": {
"port": 5001
},
"firestore": {
"port": 8080
},
"hosting": {
"port": 5000
},
"ui": {
"enabled": true
}
}
}

View file

@ -1,8 +0,0 @@
rules_version = '2';
service cloud.firestore {
match /databases/{database}/documents {
match /{document=**} {
allow read, write: if false;
}
}
}

View file

@ -1,24 +0,0 @@
module.exports = {
root: true,
parser: "@typescript-eslint/parser",
extends: [
"eslint:recommended",
"plugin:@typescript-eslint/recommended",
"prettier",
],
plugins: ["svelte3", "@typescript-eslint"],
ignorePatterns: ["*.cjs"],
overrides: [{ files: ["*.svelte"], processor: "svelte3/svelte3" }],
settings: {
"svelte3/typescript": () => require("typescript"),
},
parserOptions: {
sourceType: "module",
ecmaVersion: 2020,
},
env: {
browser: true,
es2017: true,
node: true,
},
}

11
frontend/.gitignore vendored
View file

@ -1,11 +0,0 @@
/build/
/.svelte-kit/
/package/
/node_modules/
.DS_Store
.env
.env.*
!.env.example
.vercel
.output

File diff suppressed because it is too large Load diff

View file

@ -1,36 +0,0 @@
{
"type": "module",
"scripts": {
"dev": "svelte-kit dev",
"build": "svelte-kit build",
"preview": "svelte-kit preview",
"check": "svelte-check --tsconfig ./tsconfig.json",
"check:watch": "svelte-check --tsconfig ./tsconfig.json --watch",
"lint": "prettier --ignore-path .gitignore --check --plugin-search-dir=. . && eslint --ignore-path .gitignore .",
"format": "prettier --ignore-path .gitignore --write --plugin-search-dir=. ."
},
"dependencies": {
"@fontsource/noto-sans": "^4.5.4"
},
"devDependencies": {
"@sveltejs/adapter-auto": "^1.0.0-next.17",
"@sveltejs/adapter-static": "^1.0.0-next.28",
"@sveltejs/kit": "^1.0.0-next.278",
"@types/cookie": "^0.4.1",
"@typescript-eslint/eslint-plugin": "^5.12.0",
"@typescript-eslint/parser": "^5.12.0",
"eslint": "^8.9.0",
"eslint-config-prettier": "^8.4.0",
"eslint-plugin-svelte3": "^3.4.0",
"prettier": "^2.5.1",
"prettier-plugin-svelte": "^2.6.0",
"sass": "^1.49.8",
"svelte": "^3.46.4",
"svelte-check": "^2.4.5",
"svelte-icons": "^2.1.0",
"svelte-loading-spinners": "^0.1.7",
"svelte-preprocess": "^4.10.3",
"tslib": "^2.3.1",
"typescript": "^4.5.5"
}
}

22
frontend/src/app.d.ts vendored
View file

@ -1,22 +0,0 @@
/// <reference types="@sveltejs/kit" />
// See https://kit.svelte.dev/docs/typescript
// for information about these interfaces
declare namespace App {
interface Locals {
userid: string
}
interface Platform {}
interface Session {}
interface Stuff {}
}
interface UserData {
id: string // "501277805540147220"
avatar: string // "c61056f4f187b6b3658afb68c56f3f87"
discriminator: string // "0001"
username: string // "developomp"
}

View file

@ -1,15 +0,0 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="description" content="Llama bot web interface" />
<link rel="icon" href="/assets/icon/llama-color.png" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
%svelte.head%
</head>
<body>
%svelte.body%
</body>
</html>

View file

@ -1 +0,0 @@
export const titlePrefix = "Llama Bot | "

View file

@ -1,96 +0,0 @@
<script lang="ts">
import Github from "svelte-icons/fa/FaGithub.svelte"
import Discord from "svelte-icons/fa/FaDiscord.svelte"
import Heartbeat from "svelte-icons/fa/FaHeartbeat.svelte"
import Book from "svelte-icons/fa/FaBook.svelte"
</script>
<footer>
<div class="container">
<div class="created-by">
Created by <b>developomp</b>
</div>
<!-- right links -->
<div class="icons">
<a
class="icon"
alt="Documentation"
href="https://llama-bot.github.io/llama-bot-docs/docs/web-interface/overview"
target="_"
>
<Book />
</a>
<a
class="icon"
alt="Server status"
href="https://status.llama.developomp.com"
target="_"
>
<Heartbeat />
</a>
<a
class="icon"
alt="Discord server"
href="https://discord.gg/aQqamSCUcS"
target="_"
>
<Discord />
</a>
<a
class="icon"
alt="Github repository"
href="https://github.com/llama-bot"
target="_"
>
<Github />
</a>
</div>
</div>
</footer>
<style lang="scss">
footer {
--height: 8rem;
background-color: var(--dark);
height: var(--height);
display: flex;
justify-content: center;
padding: 0 var(--h-padding);
.container {
width: min(100%, var(--max-width));
height: var(--height);
display: flex;
justify-content: space-between; // spread content
align-items: center; // vertically center elements
.created-by {
color: darkgrey;
}
.icons {
height: 24px;
display: flex;
gap: 1rem;
.icon {
color: lightgrey;
&:hover {
color: white;
}
}
}
}
}
</style>

View file

@ -1,156 +0,0 @@
<script lang="ts">
import { page } from "$app/stores"
import { userData } from "../stores"
</script>
<header>
<nav>
<div class="left-content">
<img class="icon" src="assets/icon/llama.png" alt="llama logo" />
<b>Llama Bot</b>
<div class="links">
<a
class:active={$page.url.pathname === "/"}
sveltekit:prefetch
href="/"
>
Home
</a>
<a
class:active={$page.url.pathname === "/about"}
sveltekit:prefetch
href="/about"
>
About
</a>
</div>
</div>
<div class="login-logout">
{#if $userData}
<div class="user">
<img
alt="user pfp"
src={`https://cdn.discordapp.com/avatars/${$userData.id}/${$userData.avatar}.png`}
/>
{$userData.username}#{$userData.discriminator}
</div>
{/if}
<div class="login-logout-button">
<a href={$userData ? "/api/logout" : "/api/login"}>
{$userData ? "Logout" : "Login"}
</a>
</div>
</div>
</nav>
</header>
<style lang="scss">
header {
--height: 4rem;
display: flex;
justify-content: center;
height: var(--height);
padding: 0 var(--h-padding);
background-color: var(--dark);
color: var(--light);
nav {
width: min(100%, var(--max-width)); // cap width
display: flex;
justify-content: space-between;
height: var(--height);
.left-content {
display: flex;
align-items: center;
img.icon {
width: 48px;
}
b {
font-size: 1.5rem;
}
.links {
display: flex;
gap: 0.8rem;
margin-left: 2rem;
a {
color: white;
text-decoration: none;
&.active {
border-bottom: 3px solid white;
}
}
}
}
.login-logout {
display: flex;
align-items: center;
justify-content: right;
gap: 0.5rem;
.user {
display: flex;
height: 100%;
padding: 0.1rem;
gap: 0.2rem;
align-items: center;
color: lightgray;
img {
height: 80%;
border-radius: 50%;
}
}
.login-logout-button {
display: flex;
align-items: center;
justify-content: center;
height: 100%;
background-color: indianred;
&:hover {
background-color: firebrick !important;
}
&:active {
background-color: darkred !important;
}
a {
display: flex;
width: 100%;
height: 100%;
padding: 0 1rem;
align-items: center;
color: white;
text-align: center;
text-decoration: none;
}
}
}
}
}
</style>

View file

@ -1,29 +0,0 @@
<script lang="ts">
import Heart from "svelte-icons/fa/FaHeart.svelte"
import List from "svelte-icons/fa/FaList.svelte"
import History from "svelte-icons/fa/FaHistory.svelte"
import Issue from "svelte-icons/fa/FaExclamationCircle.svelte"
const entries = [
{
title: "Favorites",
url: "/favorites",
icon: Heart,
},
{
title: "Modules",
url: "/modules",
icon: List,
},
{
title: "Logs",
url: "/logs",
icon: History,
},
{
title: "Incidents",
url: "/incidents",
icon: Issue,
},
]
</script>

View file

@ -1,84 +0,0 @@
/**
* Code taken from https://github.com/joshnuss/svelte-local-storage-store
*/
import { writable as internal, get } from "svelte/store"
import type { Writable } from "svelte/store"
declare type Updater<T> = (value: T) => T
declare type StoreDict<T> = { [key: string]: Writable<T> }
/* eslint-disable @typescript-eslint/no-explicit-any */
const stores: StoreDict<any> = {}
function stringify(value: any): string {
switch (value) {
case undefined: {
return "undefined"
}
case null: {
return "null"
}
default: {
return JSON.stringify(value)
}
}
}
function parse<T>(value: string) {
switch (value) {
case "undefined": {
return undefined
}
case "null": {
return null
}
default: {
return <T>JSON.parse(value)
}
}
}
export function writable<T>(key: string, initialValue: T): Writable<T> {
if (!stores[key]) {
const store = internal(initialValue, (set) => {
const json = localStorage.getItem(key)
if (json) set(parse<T>(json))
const handleStorage = (event: StorageEvent) => {
if (event.key === key) {
set(event.newValue ? <T>parse(event.newValue) : null)
}
}
window.addEventListener("storage", handleStorage)
return () => window.removeEventListener("storage", handleStorage)
})
const { subscribe, set } = store
stores[key] = {
set(value: T) {
localStorage.setItem(key, stringify(value))
set(value)
},
update(updater: Updater<T>) {
const value = updater(get(store))
localStorage.setItem(key, stringify(value))
set(value)
},
subscribe,
}
}
return stores[key]
}

View file

@ -1,53 +0,0 @@
<script lang="ts">
import { updateUserData } from "../stores"
import { onMount } from "svelte"
import Header from "$lib/Header.svelte"
import Footer from "$lib/Footer.svelte"
// load user data on page load
onMount(() => {
updateUserData()
})
</script>
<Header />
<main>
<slot />
</main>
<Footer />
<style lang="scss" global>
@import "@fontsource/noto-sans/index.css";
:root {
/* global CSS variables */
--dark: #001529;
--light: #f0f2f5;
--max-width: 1500px;
--h-padding: 2rem;
}
html,
body {
font-family: "Noto Sans";
height: 100vh;
margin: 0;
display: flex;
flex-direction: column;
background-color: var(--light);
}
main {
display: flex;
flex-direction: column;
flex: 1;
align-items: center;
align-self: center;
width: min(100%, var(--max-width)); // cap width
}
</style>

View file

@ -1,12 +0,0 @@
<script lang="ts">
import { titlePrefix } from "../constants"
</script>
<svelte:head>
<title>{titlePrefix}About</title>
</svelte:head>
<h1>About</h1>
<style>
</style>

View file

@ -1,12 +0,0 @@
<script lang="ts">
import { titlePrefix } from "../constants"
</script>
<svelte:head>
<title>{titlePrefix}Home</title>
</svelte:head>
<h1>Home</h1>
<style>
</style>

View file

@ -1,14 +0,0 @@
import { writable } from "./local-storage-store"
export const userData = writable<UserData>("userData", undefined)
export async function updateUserData() {
fetch("/api/user-data", { credentials: "same-origin" })
.then((data) => data.json())
.then((data) => {
userData.set(data)
})
.catch(() => {
userData.set(undefined)
})
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 20 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 20 KiB

View file

@ -1 +0,0 @@
<svg width="350" height="140" xmlns="http://www.w3.org/2000/svg" style="background:#f6f7f9"><g fill="none" fill-rule="evenodd"><path fill="#F04141" style="mix-blend-mode:multiply" d="M61.905-34.23l96.194 54.51-66.982 54.512L22 34.887z"/><circle fill="#10DC60" style="mix-blend-mode:multiply" cx="155.5" cy="135.5" r="57.5"/><path fill="#3880FF" style="mix-blend-mode:multiply" d="M208.538 9.513l84.417 15.392L223.93 93.93z"/><path fill="#FFCE00" style="mix-blend-mode:multiply" d="M268.625 106.557l46.332-26.75 46.332 26.75v53.5l-46.332 26.75-46.332-26.75z"/><circle fill="#7044FF" style="mix-blend-mode:multiply" cx="299.5" cy="9.5" r="38.5"/><rect fill="#11D3EA" style="mix-blend-mode:multiply" transform="rotate(-60 148.47 37.886)" x="143.372" y="-7.056" width="10.196" height="89.884" rx="5.098"/><path d="M-25.389 74.253l84.86 8.107c5.498.525 9.53 5.407 9.004 10.905a10 10 0 0 1-.057.477l-12.36 85.671a10.002 10.002 0 0 1-11.634 8.42l-86.351-15.226c-5.44-.959-9.07-6.145-8.112-11.584l13.851-78.551a10 10 0 0 1 10.799-8.219z" fill="#7044FF" style="mix-blend-mode:multiply"/><circle fill="#0CD1E8" style="mix-blend-mode:multiply" cx="273.5" cy="106.5" r="20.5"/></g></svg>

Before

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.5 KiB

View file

@ -1,2 +0,0 @@
User-agent: *
Disallow:

View file

@ -1,18 +0,0 @@
import adapter from "@sveltejs/adapter-static"
import preprocess from "svelte-preprocess"
/** @type {import('@sveltejs/kit').Config} */
const config = {
preprocess: preprocess(),
kit: {
adapter: adapter({
pages: "build",
assets: "build",
fallback: "index.html",
precompress: true,
}),
},
}
export default config

View file

@ -1,36 +0,0 @@
{
"compilerOptions": {
"moduleResolution": "node",
"module": "es2020",
"lib": ["es2020", "DOM"],
"target": "es2020",
/**
svelte-preprocess cannot figure out whether you have a value or a type, so tell TypeScript
to enforce using \`import type\` instead of \`import\` for Types.
*/
"importsNotUsedAsValues": "error",
/**
TypeScript doesn't know about import usages in the template because it only sees the
script of a Svelte file. Therefore preserve all value imports. Requires TS 4.5 or higher.
*/
"preserveValueImports": true,
"isolatedModules": true,
"resolveJsonModule": true,
/**
To have warnings/errors of the Svelte compiler at the correct position,
enable source maps by default.
*/
"sourceMap": true,
"esModuleInterop": true,
"skipLibCheck": true,
"forceConsistentCasingInFileNames": true,
"baseUrl": ".",
"allowJs": true,
"checkJs": true,
"paths": {
"$lib": ["src/lib"],
"$lib/*": ["src/lib/*"]
}
},
"include": ["src/**/*.d.ts", "src/**/*.js", "src/**/*.ts", "src/**/*.svelte"]
}

View file

@ -1,30 +0,0 @@
module.exports = {
root: true,
env: {
es6: true,
node: true,
},
extends: [
"eslint:recommended",
"plugin:import/errors",
"plugin:import/warnings",
"plugin:import/typescript",
"google",
"plugin:@typescript-eslint/recommended",
"prettier",
],
parser: "@typescript-eslint/parser",
parserOptions: {
project: ["tsconfig.json", "tsconfig.dev.json"],
tsconfigRootDir: __dirname,
sourceType: "module",
},
ignorePatterns: [
"/lib/**/*", // Ignore built files.
],
plugins: ["@typescript-eslint", "import"],
rules: {
quotes: ["error", "double"],
"import/no-unresolved": 0,
},
}

View file

@ -1,8 +0,0 @@
/node_modules/
# Compiled JavaScript files
/lib/
# secrets
/src/secret.json
/src/firebase-adminsdk.json

File diff suppressed because it is too large Load diff

View file

@ -1,42 +0,0 @@
{
"name": "functions",
"private": true,
"main": "lib/index.js",
"engines": {
"node": "16"
},
"scripts": {
"lint": "eslint --ext .js,.ts .",
"build": "tsc",
"serve": "npm run build && firebase emulators:start --only functions",
"shell": "npm run build && firebase functions:shell",
"start": "npm run shell",
"deploy": "firebase deploy --only functions",
"logs": "firebase functions:log"
},
"dependencies": {
"cors": "^2.8.5",
"express": "^4.17.3",
"express-session": "^1.17.2",
"firebase": "^9.6.7",
"firebase-admin": "^10.0.2",
"firebase-functions": "^3.18.1",
"passport": "^0.5.2",
"passport-discord": "^0.1.4"
},
"devDependencies": {
"@types/cors": "^2.8.12",
"@types/express": "^4.17.13",
"@types/express-session": "^1.17.4",
"@types/passport": "^1.0.7",
"@types/passport-discord": "^0.1.5",
"@typescript-eslint/eslint-plugin": "^5.12.1",
"@typescript-eslint/parser": "^5.12.1",
"eslint": "^8.9.0",
"eslint-config-google": "^0.14.0",
"eslint-config-prettier": "^8.4.0",
"eslint-plugin-import": "^2.25.4",
"firebase-functions-test": "^0.3.3",
"typescript": "^4.5.5"
}
}

View file

@ -1,73 +0,0 @@
import admin, { firestore } from "firebase-admin"
import { logger } from "firebase-functions"
interface DatabaseResult {
success: boolean
error?: string
}
export default {
/**
* Checks if a user exists in the database
*
* @param {string} uid - discord user id
*/
async findUser(uid: string): Promise<DatabaseResult> {
try {
const user = await admin.firestore().collection("users").doc(uid).get()
if (!user.exists) {
return {
success: false,
error: `user with uid ${uid} does not exist`,
}
}
return { success: true }
} catch (error) {
return { success: false, error: error.message }
}
},
/**
* Reads user data from the database
*
* @param {string} uid - discord user id
*/
async getUser(uid: string): Promise<DBUser> {
const result = await admin.firestore().collection("users").doc(uid).get()
if (!result.exists) throw new Error(`user with uid ${uid} does not exist`)
const data = result.data()
if (!data) throw new Error("User was found but failed to read the data.")
return data as DBUser
},
/**
* Create a new entry in the database
*
* @param {DBUser} data - User data to create
*/
async newUser(data: DBUser): Promise<DatabaseResult> {
try {
await firestore().doc(`/users/${data.id}`).set(data)
return { success: true }
} catch (error) {
logger.error("Error creating user", error)
return { success: false, error: error.message }
}
},
/**
* Update user data
*
* @param {Partial<DBUser>} data - Data to update
*/
async updateUser(data: Partial<DBUser>): Promise<DatabaseResult> {
await firestore().doc(`/users/${data.id}`).update(data)
return { success: true }
},
}

View file

@ -1,4 +0,0 @@
{
"pathPrefix": "/api",
"scopes": ["identify"]
}

View file

@ -1,53 +0,0 @@
import admin from "firebase-admin"
import { https } from "firebase-functions"
import express from "express"
import cors from "cors"
import session, { SessionOptions } from "express-session"
import passport from "passport"
import authRoutes from "./routes/authRoutes"
import dataRoutes from "./routes/dataRoutes"
import "./services/discordOauth"
import secret from "./secret.json"
import serviceAccountKey from "./firebase-adminsdk.json"
admin.initializeApp({
credential: admin.credential.cert(serviceAccountKey as admin.ServiceAccount),
})
const sessionOption: SessionOptions = {
secret: secret.session,
name: "__session", // https://stackoverflow.com/a/44935288/12979111
resave: false,
saveUninitialized: false,
cookie: {
maxAge: 1000 * 60 * 60 * 24 * 7, // 1 week
},
}
const app = express()
if (process.env.FUNCTIONS_EMULATOR !== "true") {
app.set("trust proxy", 1)
sessionOption.cookie = {
...sessionOption.cookie,
}
}
app.use(
cors({
origin: ["https://llama.developomp.com", "http://localhost:5000"],
credentials: true,
})
)
app.use(session(sessionOption))
app.use(passport.initialize())
app.use(passport.session())
dataRoutes(app)
authRoutes(app)
export const api = https.onRequest(app)

View file

@ -1,28 +0,0 @@
/*
* Handle authentication
*/
import { Express } from "express"
import passport from "passport"
import config from "../config.json"
export default (app: Express): void => {
// start login (redirects to /api/auth)
app.get(
config.pathPrefix + "/login",
passport.authenticate("discord", { scope: config.scopes })
)
// authenticates login (redirects to /)
app.get(
config.pathPrefix + "/auth",
passport.authenticate("discord", { successRedirect: "/" })
)
// logs out the user
app.get(config.pathPrefix + "/logout", (req, res) => {
req.logout()
res.redirect("/")
})
}

View file

@ -1,30 +0,0 @@
/*
* Handle firestore read/writes related to discord bot
*/
import { Express, Request, Response, NextFunction } from "express"
import database from "../API/database"
import config from "../config.json"
const checkIfLoggedIn = (req: Request, res: Response, next: NextFunction) => {
if (req.isAuthenticated()) return next()
res.status(401).send("Not authenticated")
}
export default (app: Express): void => {
/**
* Get user data from google firebase firestore
*/
app.get(
config.pathPrefix + "/user-data",
checkIfLoggedIn,
async (req, res) => {
res.setHeader("Cache-Control", "private")
req.user
? res.status(200).send(await database.getUser(req.user.id))
: res.status(500).send("Failed to get user")
}
)
}

View file

@ -1,68 +0,0 @@
import { logger } from "firebase-functions"
import passport from "passport"
import PassportDiscord from "passport-discord"
import database from "../API/database"
import secret from "../secret.json"
import config from "../config.json"
passport.serializeUser((user, done) => {
// `user.id` will be used in `passport.deserializeUser`
done(null, user.id)
})
passport.deserializeUser(async (id: string, done) => {
try {
const result = await database.findUser(id)
if (result.success) {
done(null, { id })
} else {
done(new Error("Failed to get user from database"))
}
} catch (error) {
logger.error("Error deserializing user", error.message)
done(error)
}
})
passport.use(
new PassportDiscord.Strategy(
{
clientID: secret.clientID,
clientSecret: secret.clientSecret,
callbackURL:
(process.env.FUNCTIONS_EMULATOR === "true"
? "http://localhost:5000"
: "https://llama.developomp.com") +
config.pathPrefix +
"/auth",
scope: config.scopes,
},
async (_accessToken, _refreshToken, profile, done) => {
try {
const result = await database.findUser(profile.id)
const data = {
avatar: profile.avatar || undefined,
discriminator: profile.discriminator,
id: profile.id,
username: profile.username,
}
if (result.success) {
await database.updateUser(data)
} else {
database.newUser(data)
}
done(null, { id: profile.id })
} catch (error) {
logger.error("Error creating a user", error)
}
}
)
)

View file

@ -1,18 +0,0 @@
declare global {
namespace Express {
// user data for the express server
export interface User {
id: string
}
}
// user data in the google firebase firestore DB
export interface DBUser {
id: string // discord user id
avatar?: string // discord avatar hash
discriminator: string // 4 digit discord discriminator
username: string // discord username
}
}
export {}

View file

@ -1,3 +0,0 @@
{
"include": [".eslintrc.js"]
}

View file

@ -1,16 +0,0 @@
{
"compilerOptions": {
"module": "commonjs",
"noImplicitReturns": true,
"noUnusedLocals": true,
"outDir": "lib",
"sourceMap": true,
"strict": true,
"target": "es2017",
"resolveJsonModule": true,
"esModuleInterop": true,
"useUnknownInCatchVariables": false
},
"compileOnSave": true,
"include": ["src"]
}