Skip to content

Commit

Permalink
RGBirdflop 8.10.0
Browse files Browse the repository at this point in the history
- Rewritten API at /api/v2
- Created API Documentation at /api/v2/docs
- Old API is now deprecated
- Changed some small tailwind classes
- Fixed export by url not working for colors
- Fixed format dropdown not updating when importing or using cookies
- Removed /resources/gradients endpoint since apparently no one was using it cuz it was erroring this whole time
  • Loading branch information
saboooor committed Jun 9, 2024
1 parent 3fcf045 commit 9f008a1
Show file tree
Hide file tree
Showing 24 changed files with 301 additions and 39 deletions.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "birdflop",
"version": "8.9.0",
"version": "8.10.0",
"homepage": "https://www.birdflop.com",
"description": "The only 501(c)(3) nonprofit Minecraft server host.",
"repository": {
Expand Down
2 changes: 1 addition & 1 deletion src/components/analyze/PaperTimings.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ export default component$(() => {
});

return (
<section class="flex mx-auto max-w-7xl px-6 items-center justify-center min-h-[calc(100svh)] pt-[72px]">
<section class="flex mx-auto max-w-7xl px-6 items-center justify-center min-h-svh pt-[72px]">
<div class="my-10 min-h-[60px]">
<h1 class="font-bold text-gray-50 text-2xl sm:text-4xl mb-2">
Paper Timings Analysis
Expand Down
2 changes: 1 addition & 1 deletion src/components/analyze/SparkProfile.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ export default component$(() => {
});

return (
<section class="flex mx-auto max-w-7xl px-6 items-center justify-center min-h-[calc(100svh)] pt-[72px]">
<section class="flex mx-auto max-w-7xl px-6 items-center justify-center min-h-svh pt-[72px]">
<div class="my-10 min-h-[60px]">
<h1 class="font-bold text-gray-50 text-2xl sm:text-4xl mb-2">
Spark Profile Analysis
Expand Down
14 changes: 12 additions & 2 deletions src/routes/[...404]/index.tsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,22 @@
import { component$ } from '@builder.io/qwik';
import type { RequestHandler } from '@builder.io/qwik-city';
import { Link, type DocumentHead } from '@builder.io/qwik-city';
import { Button, LogoBirdflop } from '@luminescent/ui';
import Background from '~/components/images/background.png?jsx';

export const onGet: RequestHandler = async ({ json, request }) => {
// check if contenttype is json
if (request.headers.get('content-type') !== 'application/json') return;

throw json(404, {
error: 'Endpoint not found.',
});
};

export default component$(() => {
return (
<section class="flex mx-auto max-w-7xl px-6 items-center justify-center min-h-[calc(100lvh-68px)]" >
<Background class="fixed inset-0 scale-110 overflow-hidden -z-10 h-[100lvh] w-[100lvw] object-cover object-center opacity-45 grayscale blur-lg" id="bg" alt="background" />
<section class="flex mx-auto max-w-7xl px-6 items-center justify-center min-h-svh" >
<Background class="fixed inset-0 scale-110 overflow-hidden -z-10 h-lvh w-lvw object-cover object-center opacity-45 grayscale blur-lg" id="bg" alt="background" />
<div class="text-red-400 text-4xl">
<LogoBirdflop confused width={100} fillGradient={['#54daf4', '#545eb6']} />
<h1 class="font-bold mb-4 mt-6">404: Page not found</h1>
Expand Down
4 changes: 2 additions & 2 deletions src/routes/acornmc/vote/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,8 @@ export default component$(() => {
});

return (
<section class="flex flex-col gap-3 mx-auto max-w-7xl px-6 items-center justify-center min-h-[calc(100svh)] pt-[72px]">
<Background class="fixed inset-0 scale-110 overflow-hidden -z-10 h-[100lvh] w-[100lvw] object-cover object-center opacity-45 blur-lg" id="bg" alt="background" />
<section class="flex flex-col gap-3 mx-auto max-w-7xl px-6 items-center justify-center min-h-svh pt-[72px]">
<Background class="fixed inset-0 scale-110 overflow-hidden -z-10 h-lvh w-lvw object-cover object-center opacity-45 blur-lg" id="bg" alt="background" />
<h1 class="font-bold text-gray-50 text-4xl sm:text-6xl mb-4">
AcornMC Vote
</h1>
Expand Down
9 changes: 7 additions & 2 deletions src/routes/api/gradient/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import type { RequestHandler } from '@builder.io/qwik-city';
import { generateOutput } from '~/components/util/RGBUtils';

export const onGet: RequestHandler = async ({ json, query }) => {
const { text, colors, format = '&#$1$2$3$4$5$6$f$c', prefix = '', bold = 'false', italic = 'false', underline = 'false', strikethrough = 'false', silent = 'false' } = Object.fromEntries(query);
const { text, colors, format = '&#$1$2$3$4$5$6$f$c', formatchar = '&', prefix = '', bold = 'false', italic = 'false', underline = 'false', strikethrough = 'false', silent = 'false' } = Object.fromEntries(query);
const options = (silent === 'true') ? {} : {
options: {
text: {
Expand All @@ -17,6 +17,10 @@ export const onGet: RequestHandler = async ({ json, query }) => {
url: 'format=&#$1$2$3$4$5$6$f$c',
description: 'The format to use for the color codes. $1 = #(r)rggbb, $2 = #r(r)ggbb, $3 = #rr(g)gbb, $4 = #rrg(g)bb, $5 = #rrgg(b)b, $6 = #rrggb(b), $f = format tags, $c = the character',
},
formatchar: {
url: 'formatchar=&',
description: 'The character to use for the format tags. (such as &l, &o, &n, &m)',
},
prefix: {
url: 'prefix=/nick',
description: 'The prefix to use for the text. Usually used for commands and stuff.',
Expand Down Expand Up @@ -44,7 +48,8 @@ export const onGet: RequestHandler = async ({ json, query }) => {
},
};
throw json(200, {
output: generateOutput(text, colors?.split(','), { color: format, char: '&' }, `${prefix}$t`, true, bold == 'true', italic == 'true', underline == 'true', strikethrough == 'true'),
WARNING: 'This endpoint is deprecated. Please use /api/v2/rgb instead.',
output: generateOutput(text, colors?.split(','), { color: format, char: formatchar }, `${prefix}$t`, true, bold == 'true', italic == 'true', underline == 'true', strikethrough == 'true'),
...options,
});
};
22 changes: 16 additions & 6 deletions src/routes/api/index.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,17 @@
export const onGet: any = async ({ json }: any) => {
throw json(200, {
endpoints: [
'/api/gradient',
],
});
import type { RequestHandler } from '@builder.io/qwik-city';

export const onGet: RequestHandler = async ({ json }) => {
throw json(200, {
endpoints: {
'/api/v2': {
type: 'GET',
description: 'View the v2 API endpoints.',
},
'/api/gradient': {
type: 'GET',
description: 'Generate a gradient.',
WARNING: '/api/gradient is deprecated. Please use /api/v2/rgb instead.',
},
},
});
};
132 changes: 132 additions & 0 deletions src/routes/api/v2/docs/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,132 @@
import { component$ } from '@builder.io/qwik';
import { routeLoader$, type DocumentHead } from '@builder.io/qwik-city';
import { Card, Header } from '@luminescent/ui';

import { DocumentOutline } from 'qwik-ionicons';
import { defaults, v3formats } from '~/components/util/PresetUtils';

export const useEndpoints = routeLoader$(async ({ url }) => {
const data = await fetch(url.origin + '/api/v2');
const json = await data.json();
const paths = Object.keys(json.endpoints);
for (const path of paths) {
const endpointData = await fetch(url.origin + path);
const endpointJson = await endpointData.json();
json.endpoints[path] = { ...json.endpoints[path], options: endpointJson.options };
}
return json;
});

export default component$(() => {
const { endpoints } = useEndpoints().value;

return <>
<section class="flex flex-col gap-3 mx-auto max-w-7xl px-6 py-16 min-h-svh">
<div>
<h1 class="flex gap-4 items-center text-gray-100 text-2xl sm:text-4xl font-bold my-12 drop-shadow-lg">
<DocumentOutline width="64" /> RGBirdflop API Docs
</h1>
<p class="text-red-500 mb-6">
The /api/gradient endpoint is deprecated and will be removed in the future in favor of this new API. Please update your code to use the new API.
</p>
<h2 class="flex gap-4 items-center text-gray-100 text-xl sm:text-3xl font-bold mb-3 drop-shadow-lg">
Get Started
</h2>
<p>
This API is used to generate RGB gradient text for Minecraft and is based on JSON. Useful for creating gradient text in your own code for anything Minecraft-related.
The API has default values that are the same as the RGBirdflop website, which are also shown in the docs below.
To generate a gradient, make a GET request to /api/v2/rgb. The API will return a JSON object with the gradient output.
</p>
<h2 class="flex gap-4 items-center text-gray-100 text-xl sm:text-3xl font-bold mt-12 mb-6 drop-shadow-lg">
Endpoints
</h2>
<div>
{Object.keys(endpoints).map((path) => <div key={path}>
<h3 class="flex gap-4 items-center text-gray-100 text-lg sm:text-2xl font-bold mb-1 drop-shadow-lg">
{endpoints[path].type} {path}
</h3>
<h4 class="flex gap-4 items-center text-gray-400 sm:text-lg mb-2 drop-shadow-lg">
{endpoints[path].description}
</h4>
<h4 class="flex gap-4 items-center text-gray-400 sm:text-lg mb-2 drop-shadow-lg">
Options
</h4>
<Card>
{Object.keys(endpoints[path].options).map(option => {
return <div key={option}>
<p class="font-bold text-white">{option}</p>
<p>type: {endpoints[path].options[option].type}</p>
<p class="text-gray-400">{endpoints[path].options[option].description}</p>
<p class="text-gray-500">default: {JSON.stringify(endpoints[path].options[option].default, null, 1)}</p>
</div>;
})}
</Card>
</div>)}
</div>
<h2 class="flex gap-4 items-center text-gray-100 text-xl sm:text-3xl font-bold mt-12 mb-6 drop-shadow-lg">
Data Models
</h2>
<Card>
<Header id="formatobject" anchor>
Format Object
</Header>
<div>
<p class="font-bold text-white">color</p>
<p class="text-red-500">required</p>
<p>type: string</p>
<p class="text-gray-400">The format to use for the color codes. $1 = #(r)rggbb, $2 = #r(r)ggbb, $3 = #rr(g)gbb, $4 = #rrg(g)bb, $5 = #rrgg(b)b, $6 = #rrggb(b), $f = format tags, $c = the character</p>
<p class="text-gray-500">example: "{defaults.format.color}" or "MiniMessage"</p>
</div>
<div>
<p class="font-bold text-white">char</p>
<p>type: string</p>
<p class="text-gray-400">The character to use for the format tags. (such as &l, &o, &n, &m)</p>
<p class="text-gray-500">example: "{defaults.format.char}"</p>
</div>
<div>
<p class="font-bold text-white">bold</p>
<p>type: string</p>
<p class="text-gray-400">The code to use for making the text bold. $t is where the output text will go. If $t is not included, the output will not show.</p>
<p class="text-gray-500">example: {v3formats.find(format => format.color == 'MiniMessage')?.bold}</p>
</div>
<div>
<p class="font-bold text-white">italic</p>
<p>type: string</p>
<p class="text-gray-400">The code to use for making the text italic. $t is where the output text will go. If $t is not included, the output will not show.</p>
<p class="text-gray-500">example: {v3formats.find(format => format.color == 'MiniMessage')?.italic}</p>
</div>
<div>
<p class="font-bold text-white">underline</p>
<p>type: string</p>
<p class="text-gray-400">The code to use for making the text underline. $t is where the output text will go. If $t is not included, the output will not show.</p>
<p class="text-gray-500">example: {v3formats.find(format => format.color == 'MiniMessage')?.underline}</p>
</div>
<div>
<p class="font-bold text-white">strikethrough</p>
<p>type: string</p>
<p class="text-gray-400">The code to use for making the text strikethrough. $t is where the output text will go. If $t is not included, the output will not show.</p>
<p class="text-gray-500">example: {v3formats.find(format => format.color == 'MiniMessage')?.strikethrough}</p>
</div>
</Card>
</div>
</section>
</>;
});

export const head: DocumentHead = {
title: 'RGBirdflop API Docs',
meta: [
{
name: 'description',
content: 'This API is used to generate RGB gradient text for Minecraft',
},
{
name: 'og:description',
content: 'This API is used to generate RGB gradient text for Minecraft',
},
{
name: 'og:image',
content: '/branding/icon.png',
},
],
};
12 changes: 12 additions & 0 deletions src/routes/api/v2/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import type { RequestHandler } from '@builder.io/qwik-city';

export const onGet: RequestHandler = async ({ json }) => {
throw json(200, {
endpoints: {
'/api/v2/rgb': {
type: 'GET',
description: 'Generate a gradient.',
},
},
});
};
80 changes: 80 additions & 0 deletions src/routes/api/v2/rgb/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
import type { RequestHandler } from '@builder.io/qwik-city';
import { v3formats } from '~/components/util/PresetUtils';
import { generateOutput } from '~/components/util/RGBUtils';
import { rgbDefaults } from '~/routes/resources/rgb';

export const onGet: RequestHandler = async ({ json, parseBody }) => {
const body = await parseBody() as any;
const { text, colors, prefixsuffix, trimspaces, bold, italic, underline, strikethrough, silent } = body ?? {};

const options = silent ? {} : {
input: {
...rgbDefaults,
...body,
},
options: {
text: {
type: 'string',
description: 'The text to use for the gradient.',
default: rgbDefaults.text,
},
colors: {
type: 'array of hex colors',
description: 'The colors to use for the gradient. Must be in hex format.',
default: rgbDefaults.colors,
},
format: {
type: 'format object - see data models in docs',
description: 'The format to use for the color and format codes. For MiniMessage, { color: "MiniMessage" } can be used.',
default: rgbDefaults.format,
},
prefixsuffix: {
type: 'string',
description: 'The prefix or suffix to use for the text. Usually used for commands and stuff. $t will be replaced with the output text, if $t is not included, the output will not show.',
default: rgbDefaults.prefixsuffix,
},
trimspaces: {
type: 'boolean',
description: 'Whether or not to trim color codes from spaces. Turn this off if you\'re using empty underlines or strikethroughs.',
default: rgbDefaults.trimspaces,
},
bold: {
type: 'boolean',
description: 'Whether or not to bold the text.',
default: rgbDefaults.bold,
},
italic: {
type: 'boolean',
description: 'Whether or not to italicize the text.',
default: rgbDefaults.italic,
},
underline: {
type: 'boolean',
description: 'Whether or not to underline the text.',
default: rgbDefaults.underline,
},
strikethrough: {
type: 'boolean',
description: 'Whether or not to strikethrough the text.',
default: rgbDefaults.strikethrough,
},
silent: {
type: 'boolean',
description: 'Set this to true to hide the options and input.',
default: false,
},
},
};

// in case stupid
// mostly just so people can just send { color: "MiniMessage" }
let format = body?.format;
if (format && !format.char && (!format.bold || !format.italic || !format.underline || !format.strikethrough)) {
format = v3formats.find(f => f.color == format.color) ?? { ...format, char: '&' };
}

throw json(200, {
output: generateOutput(text, colors, format, prefixsuffix, trimspaces, bold, italic, underline, strikethrough),
...options,
});
};
4 changes: 2 additions & 2 deletions src/routes/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,8 @@ export default component$(() => {
}));

return <>
<section class="flex mx-auto max-w-7xl px-6 items-center justify-center min-h-[calc(100svh)] pt-[72px]">
<Background class="fixed bottom-0 scale-110 overflow-hidden -z-10 h-[100lvh] w-[100lvw] object-cover object-center opacity-55" id="bg" alt="background" />
<section class="flex mx-auto max-w-7xl px-6 items-center justify-center min-h-svh pt-[72px]">
<Background class="fixed bottom-0 scale-110 overflow-hidden -z-10 h-lvh w-lvw object-cover object-center opacity-55" id="bg" alt="background" />
<div class="text-center justify-center flex relative w-full">
<div class="flex flex-col gap-2 sm:gap-6 w-full px-4">
<h1 class="text-white text-3xl sm:text-6xl font-bold animate-in fade-in slide-in-from-top-8 anim-duration-1000 drop-shadow-lg">
Expand Down
2 changes: 1 addition & 1 deletion src/routes/layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ export default component$(() => {
<Slot />
{store.cookies != 'true' &&
<div class={{
'fixed bottom-0 sm:bottom-4 w-[100vw] sm:w-auto sm:right-4 backdrop-blur-xl z-[1000] animate-in fade-in slide-in-from-bottom-8 anim-duration-1000': true,
'fixed bottom-0 sm:bottom-4 w-svw sm:w-auto sm:right-4 backdrop-blur-xl z-[1000] animate-in fade-in slide-in-from-bottom-8 anim-duration-1000': true,
}}>
<Card id="cookieprompt">
<Header subheader="We use cookies to automatically save and load your preferences.">
Expand Down
2 changes: 1 addition & 1 deletion src/routes/node-stats/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import { StatsChartOutline } from 'qwik-ionicons';
export default component$(() => {

return <>
<section class="flex flex-col gap-3 mx-auto max-w-6xl px-6 py-16 items-center min-h-[100svh]">
<section class="flex flex-col gap-3 mx-auto max-w-6xl px-6 py-16 items-center min-h-svh">
<div class="justify-center flex relative max-w-5xl px-10 py-24">
<div class="flex flex-col gap-8">
<h1 class="flex gap-4 items-center justify-center text-gray-100 text-2xl sm:text-4xl font-bold mb-4 text-center drop-shadow-lg">
Expand Down
2 changes: 1 addition & 1 deletion src/routes/plans/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ export default component$(() => {
});

return <>
<section class="flex flex-col gap-3 mx-auto max-w-6xl px-6 py-16 items-center min-h-[100svh]">
<section class="flex flex-col gap-3 mx-auto max-w-6xl px-6 py-16 items-center min-h-svh">
<div class="justify-center flex relative py-10 sm:py-24">
<div class="flex flex-col gap-8">
<h1 class="flex gap-4 items-center justify-center text-gray-100 text-2xl sm:text-4xl font-bold sm:mb-4 text-center drop-shadow-lg">
Expand Down
2 changes: 1 addition & 1 deletion src/routes/privacy/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import type { DocumentHead } from '@builder.io/qwik-city';

export default component$(() => {
return (
<section class="flex mx-auto max-w-7xl px-6 items-center justify-center min-h-[calc(100svh)] pt-[72px]">
<section class="flex mx-auto max-w-7xl px-6 items-center justify-center min-h-svh pt-[72px]">
<div class="my-10 space-y-3 min-h-[60px]">
<h1 class="text-4xl font-bold">BIRDFLOP PRIVACY POLICY</h1>
<p>Last Revised: February 29, 2024</p>
Expand Down
Loading

0 comments on commit 9f008a1

Please sign in to comment.