Nucleus transcripts, fixed season api (again), fixed hydration issues
diff --git a/pages/nucleus/transcript/about.js b/pages/nucleus/transcript/about.js
new file mode 100644
index 0000000..088e2d3
--- /dev/null
+++ b/pages/nucleus/transcript/about.js
@@ -0,0 +1,71 @@
+import React, { Component } from 'react'
+import Header from '../../../Components/Header'
+import { AutoLayout, Panel, Title, Subtitle, Text, Divider } from '../../../Components/Panels'
+import { Code } from '../../../Components/Texttools'
+import { Card, CardRow } from '../../../Components/Card'
+import HCaptcha from 'react-hcaptcha';
+import { useReward } from 'react-rewards';
+
+function About(props) {
+    const { reward, isAnimating } = useReward('confetti', 'confetti', {
+        elementSize: 12,
+        spread: 85,
+        position: "absolute",
+        colors: ["#F27878", "#E5AB71", "#E5DC71", "#A1CC65", "#68D49E", "#71AFE5", "#6576CC", "#8D58B2", "#BF5E9F"]
+    });
+
+    return (
+        <>
+            <Header
+                name="Nucleus Transcripts"
+                subtext="Review purged messages in a channel"
+                customImage={"https://assets.clicks.codes/web/logos/nucleus.svg"}
+                embedImage={"https://assets.clicks.codes/bots/nucleus/normal.png"}
+                gradient={["F27878", "D96B6B"]}
+                wave="web/waves/header/nucleus"
+                buttons={[
+                    {color: "424242", buttonText: "FFFFFF", link: "#about", text: "About"},
+                    {color: "424242", buttonText: "FFFFFF", link: "#privacy", text: "Privacy"},
+                    {color: "F27878", buttonText: "FFFFFF", link: "#invite", text: "Invite"}
+                ]}
+                season={props.season}
+            />
+            <AutoLayout>
+                <Panel halfSize={false} id="about">
+                    <Title>About Transcripts</Title>
+                    <Divider />
+                    <Text>Transcripts are generated whenever a purge command is run, or a ticket is deleted (and transcripts are enabled).</Text>
+                    <Text>These store the messages, authors, and the content for future reference.</Text>
+                    <Text>When the transcript is created, you will get a link to our website to view it.</Text>
+                    <Text>Images and files are not stored, and are not available in transcripts.</Text>
+                </Panel>
+                <Panel halfSize={true} id="privacy">
+                    <Title>Privacy</Title>
+                    <Divider />
+                    <Text>Transcripts can be viewed by anyone online if they have the URL. These are random to avoid this happening by chance.</Text>
+                    <Text>The code is long enough that it is hard to guess any specific code. The URL is not linked to your server in any way.</Text>
+                    <Text>All transcripts for your server can be deleted from <Code colour="F27878">/privacy</Code>.</Text>
+                </Panel>
+                <Panel halfSize={true} id="invite">
+                    <Title>Invite</Title>
+                    <Divider />
+                    <CardRow>
+                        <Card
+                            wave="nucleus"
+                            icon="bots/nucleus/circle"
+                            buttonText={"FFFFFF"} gradient={["F27878", "D96B6B"]}
+                            title="Nucleus"
+                            subtext="Invite Nucleus to your server"
+                            buttons={[
+                                {color: "424242", link: "https://discord.com/api/oauth2/authorize?client_id=715989276382462053&permissions=121295465718&scope=bot%20applications.commands", text: "Invite"}
+                            ]}
+                            url="https://discord.com/api/oauth2/authorize?client_id=715989276382462053&permissions=121295465718&scope=bot%20applications.commands"
+                        />
+                    </CardRow>
+                </Panel>
+            </AutoLayout>
+        </>
+    )
+}
+
+export default About;
\ No newline at end of file
diff --git a/pages/nucleus/transcript/index.js b/pages/nucleus/transcript/index.js
new file mode 100644
index 0000000..1c9e88f
--- /dev/null
+++ b/pages/nucleus/transcript/index.js
@@ -0,0 +1,57 @@
+import Axios from 'axios';
+import React from 'react';
+
+function Index(props) {
+    return <>
+    <div style={{
+        width: "100vw",
+        height: "40px",
+        backgroundColor: "#F27878",
+        display: "flex",
+        justifyContent: "left",
+        alignItems: "center",
+        paddingLeft: "25px",
+        color: "white",
+        fontSize: "1.5em",
+    }}>Nucleus Transcripts</div>
+    <div style={{
+        height: "100vw",
+        width: "100vw",
+        backgroundColor: "var(--theme-ui-colors-background)",
+        margintop: "-50px",
+        padding: "25px",
+        paddingTop: "10px",
+        transition: "all 0.3s ease-in-out"
+    }}>
+        <p>{props.humanReadable}</p>
+    </div>
+</>
+}
+
+export default Index;
+export async function getServerSideProps(ctx) {
+    if(!ctx.query.code) {
+        return {
+            redirect: {
+                destination: '/nucleus/transcript/about',
+                permanent: true
+            }
+        }
+    }
+    let code;
+    try {
+        code = await Axios.get(`http://localhost:10000/transcript/${ctx.query.code}/human`);
+    } catch (e) {
+        return {
+            redirect: {
+                destination: '/nucleus/transcript/invalid',
+                permanent: true
+            }
+        }
+    }
+    return {
+        props: {
+            humanReadable: code.data
+        }
+    }
+}
\ No newline at end of file
diff --git a/pages/nucleus/transcript/invalid.js b/pages/nucleus/transcript/invalid.js
new file mode 100644
index 0000000..8491aeb
--- /dev/null
+++ b/pages/nucleus/transcript/invalid.js
@@ -0,0 +1,26 @@
+import { Component } from 'react'
+import Link from 'next/link'
+import Header from '../../../Components/Header'
+
+class Failed extends Component {
+    constructor(props) {
+        super(props)
+    }
+
+    render() {
+        return (
+            <Header
+                name="Transcript does not exist"
+                subtext={<p>No transcripts matched that code. If you believe this is a mistake, please submit a report in <Link href="https://discord.gg/bPaNnxe" target="_blank" rel="noopener noreferrer">our server</Link></p>}
+                gradient={["F27878", "D96B6B"]}
+                wave="web/waves/header/nucleus"
+                buttons={[]}
+                fullscreen={true}
+                season={this.props.season}
+            />
+        )
+    }
+
+}
+
+export default Failed;
\ No newline at end of file
diff --git a/pages/nucleus/transcript/testing.js b/pages/nucleus/transcript/testing.js
new file mode 100644
index 0000000..ac0240b
--- /dev/null
+++ b/pages/nucleus/transcript/testing.js
@@ -0,0 +1,54 @@
+import React from 'react';
+
+function Testing(props) {
+    return <>
+        <div style={{
+            width: "100vw",
+            height: "40px",
+            backgroundColor: "#F27878",
+            display: "flex",
+            justifyContent: "left",
+            alignItems: "center",
+            paddingLeft: "25px",
+            color: "white",
+            fontSize: "1.5em",
+        }}>Nucleus Transcripts</div>
+        <div style={{
+            height: "100vw",
+            width: "100vw",
+            backgroundColor: "var(--theme-ui-colors-background)",
+            margintop: "-50px",
+            padding: "25px",
+            paddingTop: "10px",
+            transition: "all 0.3s ease-in-out"
+        }}>
+            <p>{props.humanReadable}</p>
+        </div>
+    </>
+}
+
+export default Testing;
+export async function getServerSideProps(ctx) {
+    if(!ctx.query.code) {
+        return {
+            redirect: {
+                destination: '/nucleus/transcript/about',
+                permanent: true
+            }
+        }
+    }
+    if (ctx.query.code === "test") {
+        return {
+            props: {
+                humanReadable: "This is a test string! It should render correctly on the page"
+            }
+        }
+    } else {
+        return {
+            redirect: {
+                destination: '/nucleus/transcript/invalid',
+                permanent: true
+            }
+        }
+    }
+}
\ No newline at end of file
diff --git a/pages/nucleus/verify/failure.js b/pages/nucleus/verify/failure.js
index 8581c18..12fdc26 100644
--- a/pages/nucleus/verify/failure.js
+++ b/pages/nucleus/verify/failure.js
@@ -1,4 +1,5 @@
 import { Component } from 'react'
+import Link from 'next/link'
 import Header from '../../../Components/Header'
 
 class Failed extends Component {
@@ -10,7 +11,9 @@
         return (
             <Header
                 name="Verification failed"
-                subtext={<p>Please try again, and if the error persists please contact us at <a href="mailto:verification@clicks.codes" target="_blank" rel="noopener noreferrer">verification@clicks.codes</a></p>}
+                subtext={
+                    <p>Please try again, and if the error persists please contact us at <Link href="mailto:verification@clicks.codes" target="_blank" rel="noopener noreferrer">verification@clicks.codes</Link></p>
+                }
                 gradient={["F27878", "D96B6B"]}
                 wave="web/waves/header/nucleus"
                 buttons={[]}