Nucleus transcripts, fixed season api (again), fixed hydration issues
diff --git a/pages/api/season.js b/pages/api/season.js
index c3066cc..2603a52 100644
--- a/pages/api/season.js
+++ b/pages/api/season.js
@@ -2,6 +2,14 @@
return Math.floor((new Date().getTime() - date.getTime()) / (1000 * 60 * 60 * 24))
}
+function daysSinceDate(date) {
+ // If the date is after today, make it last year
+ if (date > new Date()) {
+ date.setFullYear(date.getFullYear() - 1);
+ }
+ return Math.floor((new Date().getTime() - date.getTime()) / (1000 * 60 * 60 * 24));
+}
+
function getSeason() {
let year = new Date().getFullYear();
@@ -10,7 +18,8 @@
halloween: [new Date(`${year}-10-25`), new Date(`${year}-11-1`)],
trans: [new Date(`${year}-11-13`), new Date(`${year}-11-19`)],
christmas: [new Date(`${year}-12-1`), new Date(`${year}-12-26`)],
- aprilFools: [new Date(`${year}-04-01`), new Date(`${year}-04-01`)]
+ aprilFools: [new Date(`${year}-04-01`), new Date(`${year}-04-01`)],
+ fake: [new Date(`${year}-01-01`), new Date(`${year}-01-01`)]
}
const filePaths = {
normal: "normal",
@@ -23,19 +32,19 @@
let current = new Date();
let currentSeason = Object.keys(dates).find((str) => current >= dates[str][0] && current <= dates[str][1]) || "normal";
- let daysIntoSeason;
+ let currentDaysIntoSeason;
if (currentSeason !== "normal") {
- daysIntoSeason = daysIntoSeason(dates[currentSeason][0])
+ currentDaysIntoSeason = daysIntoSeason(dates[currentSeason][0])
} else {
- // Calculate the days from the end of each season
- let days = Object.keys(dates).map((str) => daysIntoSeason(dates[str][1])).filter((num) => num > 0);
- daysIntoSeason = Math.min(...days);
+ // Calculate how many days it has been since each season ended
+ let days = Object.keys(dates).map((str) => daysSinceDate(dates[str][1]))
+ currentDaysIntoSeason = Math.min(...days);
}
return {
season: currentSeason,
filePath: filePaths[currentSeason],
- daysIntoSeason: daysIntoSeason
+ daysIntoSeason: currentDaysIntoSeason
}
}
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={[]}