Content Migration from websites repo
This commit is contained in:
parent
c1d93528d7
commit
ba88a7adc5
22 changed files with 8767 additions and 1 deletions
22
pages/_app.tsx
Normal file
22
pages/_app.tsx
Normal file
|
@ -0,0 +1,22 @@
|
|||
import '/styles/globals.css'
|
||||
import type { ReactElement, ReactNode } from 'react'
|
||||
import Layout from '../components/layout'
|
||||
import type { NextPage } from 'next'
|
||||
import { AppProps } from 'next/app';
|
||||
|
||||
|
||||
export type NextPageWithLayout<P = {}, IP = P> = NextPage<P, IP> & {
|
||||
getLayout?: (page: ReactElement) => ReactNode
|
||||
}
|
||||
|
||||
export type AppPropsWithLayout = AppProps & {
|
||||
Component: NextPageWithLayout
|
||||
}
|
||||
|
||||
export default function Website({ Component, pageProps }: AppPropsWithLayout) {
|
||||
// Use the layout defined at the page level, if available
|
||||
const getLayout = Component.getLayout ?? ((page) => (
|
||||
<Layout>{page}</Layout>))
|
||||
|
||||
return getLayout(<Component {...pageProps} />)
|
||||
}
|
20
pages/about.tsx
Normal file
20
pages/about.tsx
Normal file
|
@ -0,0 +1,20 @@
|
|||
import Head from 'next/head'
|
||||
import styles from '/styles/Home.module.css'
|
||||
|
||||
export default function About() {
|
||||
return (
|
||||
<>
|
||||
<Head>
|
||||
<title>Neshura Servers</title>
|
||||
<meta charSet='utf-8' />
|
||||
<link rel="icon" href="/favicon.ico" />
|
||||
</Head>
|
||||
<h1 className={styles.title}>
|
||||
About
|
||||
</h1>
|
||||
<p className={styles.description}>
|
||||
This website is primarily for managing my game servers in one spot
|
||||
</p>
|
||||
</>
|
||||
)
|
||||
}
|
56
pages/api/zomboid.tsx
Normal file
56
pages/api/zomboid.tsx
Normal file
|
@ -0,0 +1,56 @@
|
|||
import fsPromises from 'fs/promises'
|
||||
import path from 'path'
|
||||
import type { NextApiRequest, NextApiResponse } from 'next'
|
||||
import { CustomLink } from '../../interfaces/LinkTypes';
|
||||
|
||||
export default async function userHandler(req: NextApiRequest, res: NextApiResponse) {
|
||||
const {
|
||||
body: { ip, status, key },
|
||||
method,
|
||||
} = req
|
||||
|
||||
const filePath = path.join(process.cwd(), '/data/zomboid.json')
|
||||
const jsonBuffer = await fsPromises.readFile(filePath)
|
||||
const jsonData = JSON.parse(jsonBuffer.toString())
|
||||
|
||||
switch (method) {
|
||||
case 'GET':
|
||||
res.status(200).json(jsonData)
|
||||
break
|
||||
case 'PUT':
|
||||
if (key == "#inFamous3") {
|
||||
if (ip != jsonData.currentIP) {
|
||||
jsonData.historicIP.unshift(jsonData.currentIP)
|
||||
if (Object.keys(jsonData.historicIP).length > 10) {
|
||||
jsonData.historicIP.pop()
|
||||
}
|
||||
jsonData.currentIP = ip
|
||||
}
|
||||
jsonData.status = status
|
||||
|
||||
modifyServerStatus(ip, status)
|
||||
|
||||
|
||||
await fsPromises.writeFile(filePath, JSON.stringify(jsonData, null, 2))
|
||||
|
||||
res.status(200).json(jsonData)
|
||||
}
|
||||
else {
|
||||
res.status(401).json("wrong key")
|
||||
}
|
||||
break
|
||||
default:
|
||||
res.setHeader('Allow', ['GET', 'PUT'])
|
||||
res.status(405).end(`Method ${method} Not Allowed`)
|
||||
}
|
||||
}
|
||||
|
||||
async function modifyServerStatus(ip: String, status: String) {
|
||||
const filePath = path.join(process.cwd(), '/confs/pages.json')
|
||||
const jsonBuffer = await fsPromises.readFile(filePath)
|
||||
const data = JSON.parse(jsonBuffer.toString())
|
||||
data.servers.zomboid.ip = ip
|
||||
data.servers.zomboid.status = status
|
||||
await fsPromises.writeFile(filePath, JSON.stringify(data, null, 2))
|
||||
return data
|
||||
}
|
65
pages/games.tsx
Normal file
65
pages/games.tsx
Normal file
|
@ -0,0 +1,65 @@
|
|||
import Head from 'next/head'
|
||||
import Link from 'next/link'
|
||||
import styles from '/styles/Home.module.css'
|
||||
import fsPromises from 'fs/promises'
|
||||
import path from 'path'
|
||||
import type { CustomLink, LinkList } from '../interfaces/LinkTypes'
|
||||
|
||||
function Servers(props: LinkList) {
|
||||
const serverList = props.games
|
||||
return (
|
||||
<>
|
||||
<Head>
|
||||
<title>Neshura Servers</title>
|
||||
<meta charSet='utf-8' />
|
||||
<link rel="icon" href="/favicon.ico" />
|
||||
</Head>
|
||||
|
||||
<h1 className={styles.title}>
|
||||
Server List
|
||||
</h1>
|
||||
|
||||
<p className={styles.description}>
|
||||
Lists all available Services, probably up-to-date
|
||||
</p>
|
||||
<div className={styles.grid}>
|
||||
{Object.values(serverList).map((item: CustomLink) => {
|
||||
if (item.href != null) {
|
||||
return (
|
||||
<Link key={item.name} href={item.href}>
|
||||
<a className={styles.contentcard}>
|
||||
<div className={styles.contenttitle}><h2>{item.name }</h2></div>
|
||||
<div><p>{item.desc}</p></div>
|
||||
<div><p>{item.ip }</p></div>
|
||||
<div className={item.status == "Online" ? styles.contentonline : styles.contentoffline}><p>{item.status}</p></div>
|
||||
</a>
|
||||
</Link>
|
||||
)
|
||||
}
|
||||
else {
|
||||
return (
|
||||
<a key={item.name} className={styles.contentcardstatic}>
|
||||
<div className={styles.contenttitle}><h2>{item.name }</h2></div>
|
||||
<div><p>{item.desc}</p></div>
|
||||
<div><p>{item.ip}</p></div>
|
||||
<div className={item.status == "Online" ? styles.contentonline : styles.contentoffline}><p>{item.status}</p></div>
|
||||
</a>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
)}
|
||||
</div>
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
export async function getServerSideProps() {
|
||||
const filePath = path.join(process.cwd(), '/confs/pages.json')
|
||||
const jsonData = await fsPromises.readFile(filePath)
|
||||
const list = JSON.parse(jsonData.toString())
|
||||
|
||||
return { props: list }
|
||||
}
|
||||
|
||||
export default Servers
|
46
pages/index.tsx
Normal file
46
pages/index.tsx
Normal file
|
@ -0,0 +1,46 @@
|
|||
import Head from 'next/head'
|
||||
import Link from 'next/link'
|
||||
import styles from '/styles/Home.module.css'
|
||||
|
||||
export default function Home() {
|
||||
return (
|
||||
<>
|
||||
<Head>
|
||||
<title>Neshura Servers</title>
|
||||
<meta charSet='utf-8' />
|
||||
<link rel="icon" href="/favicon.ico" />
|
||||
</Head>
|
||||
|
||||
<h1 className={styles.title}>
|
||||
Welcome to my Servers Webpage
|
||||
</h1>
|
||||
|
||||
<p className={styles.description}>
|
||||
Feel free to look around
|
||||
</p>
|
||||
<div className={styles.grid}>
|
||||
<Link key="about" href="/about">
|
||||
<a className={styles.card}>
|
||||
<h2>About →</h2>
|
||||
<p>Useless Info, don't bother</p>
|
||||
</a>
|
||||
</Link>
|
||||
|
||||
<Link key="servers" href="/games">
|
||||
<a className={styles.card}>
|
||||
<h2>Games →</h2>
|
||||
<p>List of all available Servers</p>
|
||||
</a>
|
||||
</Link>
|
||||
|
||||
<Link key="services" href="/services">
|
||||
<a className={styles.card}>
|
||||
<h2>Services →</h2>
|
||||
<p>List of available Services</p>
|
||||
</a>
|
||||
</Link>
|
||||
|
||||
</div>
|
||||
</>
|
||||
)
|
||||
}
|
139
pages/services.tsx
Normal file
139
pages/services.tsx
Normal file
|
@ -0,0 +1,139 @@
|
|||
import Head from 'next/head'
|
||||
import Link from 'next/link'
|
||||
import styles from '/styles/Home.module.css'
|
||||
import fsPromises from 'fs/promises'
|
||||
import path, { resolve } from 'path'
|
||||
import type { CustomLink, LinkList } from '../interfaces/LinkTypes'
|
||||
import Dockerode from 'dockerode';
|
||||
|
||||
|
||||
function Services(props: LinkList) {
|
||||
const serviceList = props.services
|
||||
return (
|
||||
<>
|
||||
<Head>
|
||||
<title>Neshura Servers</title>
|
||||
<meta charSet='utf-8' />
|
||||
<link rel="icon" href="/favicon.ico" />
|
||||
</Head>
|
||||
|
||||
<h1 className={styles.title}>
|
||||
Service List
|
||||
</h1>
|
||||
|
||||
<p className={styles.description}>
|
||||
Lists all available Services, most likely up-to-date
|
||||
</p>
|
||||
<div className={styles.grid}>
|
||||
{serviceList.map((item: CustomLink) => (
|
||||
<Link key={item.name} href={item.href}>
|
||||
<a className={styles.contentcard}>
|
||||
<div className={styles.contenttitle}><h2>{item.name}</h2></div>
|
||||
<div className={item.status == "Online" ? styles.contentonline : styles.contentoffline}>{item.status}</div>
|
||||
<div><p>{item.desc}</p></div>
|
||||
<div className={styles.cardwarn}><p>{item.warn}</p></div>
|
||||
</a>
|
||||
</Link>
|
||||
))}
|
||||
</div>
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
// Gets a List of all services specified in /confs/pages.json
|
||||
export async function getServerSideProps() {
|
||||
const filePath = path.join(process.cwd(), './confs/pages.json')
|
||||
// TODO: look into asyncing this API call
|
||||
const jsonData = await fsPromises.readFile(filePath)
|
||||
const list = JSON.parse(jsonData.toString())
|
||||
for (let index = 0; index < list.services.length; index++) {
|
||||
// TODO: look into asyncing this as well
|
||||
await status(list.services[index]);
|
||||
}
|
||||
return { props: list }
|
||||
}
|
||||
|
||||
// reversing this to loop over given entries for every found container would probably improve latency
|
||||
async function status(entry: CustomLink) {
|
||||
// for now only the BRR7-4800U can be used with Docker, needs changing once more Servers are used
|
||||
// TODO: support multiple locations for docker
|
||||
if (entry.location === "brr7-4800u") {
|
||||
// app in this context means any non-docker page
|
||||
if (entry.type === "app") {
|
||||
|
||||
let data = new Response();
|
||||
try {
|
||||
await fetch(entry.href).then((response: Response) => data = response);
|
||||
}
|
||||
catch (e) {
|
||||
console.log(e)
|
||||
return (entry.status = "Offline");
|
||||
}
|
||||
|
||||
if (data.ok) {
|
||||
if (data.status == 200 || data.status == 301 || data.status == 302) {
|
||||
return (entry.status = "Online");
|
||||
}
|
||||
else return (entry.status = "Offline");
|
||||
}
|
||||
else return (entry.status = "Offline");
|
||||
}
|
||||
else if (entry.type === "docker") {
|
||||
var Docker = require('dockerode');
|
||||
|
||||
// TODO: read these paths from some config instead of hardcoding them
|
||||
const options = {
|
||||
socketPath: '/var/run/docker.sock',
|
||||
path: '/v1.41/containers/json'
|
||||
};
|
||||
var docker = new Docker({ socketPath: options.socketPath });
|
||||
|
||||
// default is set as Offline, prevents uncaught cases without set status
|
||||
entry.status = "Offline";
|
||||
// TODO: async possible?
|
||||
await docker.listContainers({all: true}).then(
|
||||
((containers: Dockerode.ContainerInfo[]) => {
|
||||
// Loop over every found container and compare to the entry provided
|
||||
containers.forEach((element: Dockerode.ContainerInfo) => {
|
||||
element.Names.forEach((containerName: string) => {
|
||||
if (containerName.startsWith("/")) {
|
||||
containerName = containerName.substring(1);
|
||||
}
|
||||
if (containerName === entry.docker_container_name) {
|
||||
entry.status = "Online";
|
||||
}
|
||||
});
|
||||
if (entry.docker_container_name == null) {
|
||||
console.log("MISSING DOCKER CONTAINER NAME FOR " + entry.name);
|
||||
entry.status = "ERROR";
|
||||
}
|
||||
});
|
||||
})
|
||||
);
|
||||
}
|
||||
else { entry.status = "ERROR" }
|
||||
return;
|
||||
}
|
||||
// for non-local locations pinging can be used to see if they're up
|
||||
else if (entry.location != "") {
|
||||
let data: Response;
|
||||
try {
|
||||
data = await fetch(entry.href);
|
||||
}
|
||||
catch (e) {
|
||||
console.log(e)
|
||||
return (entry.status = "Offline");
|
||||
}
|
||||
|
||||
if (data.ok) {
|
||||
if (data.status == 200 || data.status == 301 || data.status == 302) {
|
||||
return (entry.status = "Online");
|
||||
}
|
||||
else return (entry.status = "Offline");
|
||||
}
|
||||
else return (entry.status = "Offline");
|
||||
}
|
||||
else { return (entry.status = "ERROR") }
|
||||
}
|
||||
|
||||
export default Services
|
Loading…
Add table
Add a link
Reference in a new issue