Compare commits

...

3 Commits

Author SHA1 Message Date
Jill 607f304359
update invite link to include perms 2023-11-27 19:24:09 +03:00
Jill beeb89b2c4
update site a lil 2023-11-27 19:22:58 +03:00
Jill 5ff705d779
make random words a little more sane 2023-11-27 18:22:59 +03:00
8 changed files with 110 additions and 17 deletions

View File

@ -2,12 +2,9 @@ import { Interaction, Message, TextBasedChannel, User } from 'discord.js';
import * as log from '../lib/log';
export const RANDOM_WORDS = [
'tarsorado', 'aboba', 'robtop', 'viprin', 'milk', 'milking station', 'radiation', 'extreme', 'glogging', 'glogged',
'penis', 'deadlocked', 'cream', 'dragon cream', 'urine', 'communal', 'piss', 'matpat', 'big and round', 'easy',
'cum', 'glue', 'tampon', 'contaminated water', 'centrifuge', 'inflation', 'plutonium', 'uranium', 'thorium',
'imposter', 'sounding', '💥', '🥵', '🎊', '!!!', '...', '???', '?..', '?!', '!', '?', 'balls itch', 'robert',
'gas leak', 'among us', 'stick a finger', 'overclock', 'breed', 'gay sex', 'breedable', 'cock vore', 'appendix',
'mukbang', 'edging', 'onlyfans', 'productive', 'mandelbrot', 'novosibirsk', 'oops!', 'farting', 'memory leak',
'tarsorado', 'aboba', 'radiation', 'extreme', 'glogging', 'glogged', 'penis', 'easy', 'glue', 'contaminated water',
'centrifuge', 'plutonium', 'uranium', 'thorium', 'imposter', '💥', '🥵', '🎊', '!!!', '...', '???', '?..', '?!',
'!', '?', 'balls itch', 'gas leak', 'among us', 'overclock', 'mandelbrot', 'novosibirsk', 'oops!', 'memory leak',
'pepsi can'
];

31
src/web/docs.ts Normal file
View File

@ -0,0 +1,31 @@
import { outdent } from 'outdent';
export const docs: Record<string, string> = {
introduction: outdent`
<p>
<b>Jillo</b> is yet another fun / utility / whatever Swiss knife Discord bot, except this time it's <em>better than the other ones, I promise, please,
you'll have to trust me on this one, please</em>
</p>
<p>
The main big feature currently is the <b>RPG</b>, which lets you scavenge for items, craft them up into weapons and fight others, completely
customizable by server admins to their liking! It's a little rough, officially considered in <em>beta</em>, but you're free to toy around with it!
</p>
<p>
Aside from that, you also have your classic <b>self-assignable roles</b> for colors and pronouns, <b>silly text games</b> somewhat like Jackbox but
playable all inside Discord, and a few little silly miscellaneous commands. If it seems a little overengineered - that's because it is, but also
because a good chunk of the bot's functionality is only relevant inside <em>specific friend groups</em> the bot was made for.
</p>
<p>
That's about it! Here's a few links for your consideration:
</p>
<el>
<li><a href="https://discord.com/oauth2/authorize?client_id=898850107892596776&permissions=268443648&scope=bot" target="_blank" rel="noopener">Invite</a> the bot to your server</li>
<li><a href="https://git.oat.zone/dark-firepit/jillo-bot" target="_blank" rel="noopener">View the source code</a> that's completely open for you to peek at</li>
</el>
<img class="jillo" src="/assets/jillo.png" width="150" height="200">
`,
};
export function formatTitle(name: string) {
return name.replace('-', ' ');
}

View File

@ -1,4 +1,4 @@
import express from 'express';
import express, { NextFunction, Response } from 'express';
import { create } from 'express-handlebars';
import * as log from '../lib/log';
import { CustomItem, Counter, CustomCraftingRecipe, db } from '../lib/db';
@ -6,6 +6,7 @@ import { defaultItems } from '../lib/rpg/items';
import { Client, CDN } from 'discord.js';
import { getToken, getSessionString, getSession, setSession, updateCookie } from './oauth2';
import { getUser, getGuilds } from './user';
import { docs, formatTitle } from './docs';
async function getGuildInfo(bot: Client, id: string) {
const guild = await bot.guilds.cache.get(id);
@ -68,13 +69,13 @@ export async function startServer(bot: Client, port: number) {
});
});
app.get('/', async (req, res) => {
app.get('/', async (req, res, next) => {
const code = req.query.code as string;
if (code) {
try {
const resp = await getToken(bot, code);
if (!resp) return res.status(400).send('Invalid code provided');
if (!resp) return next({ http: 400, message: 'Invalid code provided' });
const sessionId = await getSessionString(decodeURIComponent(req.headers.cookie || ''));
@ -89,8 +90,7 @@ export async function startServer(bot: Client, port: number) {
return res.redirect('/profile');
} catch (err) {
log.error(err);
return res.status(500);
return next(err);
}
}
@ -115,6 +115,7 @@ export async function startServer(bot: Client, port: number) {
//res.sendFile('profile/index.html', { root: 'static/' });
res.render('profile', {
title: 'profile',
user,
guilds: await Promise.all(
guilds.map(async guild =>
@ -124,7 +125,40 @@ export async function startServer(bot: Client, port: number) {
});
});
app.get('/docs/:name', async (req, res, next) => {
const { name } = req.params;
if (!name) return res.redirect('/docs/introduction');
const content = docs[name];
if (!content) return next();
res.render('docs', {
name: formatTitle(name),
content: content,
sidebar: Object.keys(docs).map(d => ({ name: formatTitle(d), value: d })),
});
});
app.use(express.static('static/'));
// error handling
app.use((req, res, next) => {
// since this is the last non-error-handling middleware, assume 404
next({ http: '404', message: `${req.path} not found` });
});
// eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/no-unused-vars
app.use((err: Error | any, req: any, res: Response, next: NextFunction) => {
log.error(err);
const status = err.http ? err.http : 500;
res.status(status).render('error', {
path: req.path,
status,
message: err.message,
});
});
app.listen(port, () => log.info(`web interface listening on ${port}`));
}

View File

@ -59,19 +59,20 @@ a:hover {
min-height: 100%;
flex: 1 0 auto;
}
#main img {
.jillo {
display: block;
height: 18rem;
width: auto;
margin: 0 auto;
animation: 1s popup;
animation-timing-function: cubic-bezier(0.34, 1.56, 0.64, 1);
transition: transform 0.15s, opacity 0.1s;
}
#main > img:active {
.jillo:active {
transform: scale(0.97);
opacity: 0.9;
}
#main > :not(img) {
#main > :not(.jillo) {
animation: 0.8s fadein;
}
#main h1 {
@ -350,4 +351,18 @@ pre {
}
.guild .info {
color: var(--text-color-light);
}
.status-code {
font-size: 10rem;
line-height: 1.0;
background: repeating-linear-gradient(98deg, rgba(190,190,190,1) 0%, rgba(190,190,190,1) 10%, rgba(207,207,207,1) 10%, rgba(207,207,207,1) 20%);
background-clip: text;
-webkit-text-fill-color: transparent;
-webkit-background-clip: text;
font-weight: bolder;
text-align: center;
}
.error {
text-align: center;
}

9
views/docs.handlebars Normal file
View File

@ -0,0 +1,9 @@
<div class="docs-layout">
<div class="sidebar">
</div>
<div class="main">
<h1>{{ name }}</h1>
{{{ content }}}
</div>
</div>

5
views/error.handlebars Normal file
View File

@ -0,0 +1,5 @@
<div class="status-code">{{status}}</div>
<div class="error">
Error accessing {{ path }}: {{ message }}
</div

View File

@ -25,12 +25,14 @@
<img class="avatar" src="{{avatar user.id user.avatar}}" width="128" height="128">
</div>
<div id="main">
<img src="/assets/jillo.png" width="150" height="200">
<img class="jillo" src="/assets/jillo.png" width="150" height="200">
<h1>jillo!</h1>
<div>
<a href="https://discord.com/oauth2/authorize?client_id=898850107892596776&scope=bot" target="_blank" rel="noopener">invite</a>
<a href="https://discord.com/oauth2/authorize?client_id=898850107892596776&permissions=268443648&scope=bot" target="_blank" rel="noopener">invite</a>
&middot;
<a href="https://git.oat.zone/dark-firepit/jillo-bot" target="_blank" rel="noopener">repo</a>
&middot;
<a href="/docs/introduction">what</a>
</div>
<div id="status">
&middot;&middot;&middot;

View File

@ -3,7 +3,7 @@
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>jillo</title>
<title>{{title}} - jillo</title>
<meta name="theme-color" content="light dark">
<link href="/style.css" rel="stylesheet">