init
Gitea Auto Deploy / Deploy-Container (push) Failing after 52s

This commit is contained in:
2026-04-13 18:05:27 +07:00
commit c77f4a2cb9
207 changed files with 18035 additions and 0 deletions
+25
View File
@@ -0,0 +1,25 @@
import { getDataCache } from "@/lib/cache/cache"
export async function GET(
req: Request,
{ params }: { params: Promise<{ name: string }> }
) {
const { name } = await params
const item = getDataCache(name)
if (!item) {
return new Response("Not found", { status: 404 })
}
const headers: Record<string, string> = {
"Content-Type": "application/json",
"Cache-Control": "public, max-age=3600"
}
if (item.type === "br") {
headers["Content-Encoding"] = "br"
}
return new Response(new Uint8Array(item.buf), { headers })
}
+102
View File
@@ -0,0 +1,102 @@
import { NextRequest, NextResponse } from 'next/server'
import axios from 'axios'
import net from 'net'
function isPrivateHost(hostname: string): boolean {
if (
hostname === 'localhost' ||
hostname.startsWith('127.') ||
hostname.startsWith('10.') ||
hostname.startsWith('192.168.') ||
/^172\.(1[6-9]|2[0-9]|3[0-1])\./.test(hostname)
) {
return true
}
if (net.isIP(hostname)) {
return true
}
return false
}
export async function GET(req: NextRequest) {
try {
const { searchParams } = new URL(req.url)
const targetUrl = searchParams.get("url")
if (!targetUrl) {
return NextResponse.json({ error: "Missing url" }, { status: 400 })
}
const response = await fetch(targetUrl)
if (!response.ok) {
return NextResponse.json({ error: "Failed to fetch image" }, { status: 500 })
}
const buffer = await response.arrayBuffer()
return new NextResponse(buffer, {
headers: {
"Content-Type": response.headers.get("content-type") || "image/png",
"Cache-Control": "public, max-age=3600",
"Access-Control-Allow-Origin": "*",
},
})
} catch (e: unknown) {
return NextResponse.json({ error: (e as Error)?.message }, { status: 500 })
}
}
export async function POST(request: NextRequest) {
try {
const body = await request.json()
const { serverUrl, method, ...payload } = body
if (!serverUrl) {
return NextResponse.json({ error: 'Missing serverUrl' }, { status: 400 })
}
if (!method) {
return NextResponse.json({ error: 'Missing method' }, { status: 400 })
}
let url = serverUrl.trim()
if (!url.startsWith('http://') && !url.startsWith('https://')) {
url = `http://${url}`
}
const parsed = new URL(url)
if (isPrivateHost(parsed.hostname)) {
return NextResponse.json(
{ error: `Connection to private/internal address (${parsed.hostname}) is not allowed` },
{ status: 403 }
)
}
let response
switch (method.toUpperCase()) {
case 'GET':
const queryString = new URLSearchParams(payload as Record<string, string>).toString()
const fullUrl = queryString ? `${url}?${queryString}` : url
response = await axios.get(fullUrl)
break
case 'POST':
response = await axios.post(url, payload)
break
case 'PUT':
response = await axios.put(url, payload)
break
case 'DELETE':
response = await axios.delete(url, { data: payload })
break
default:
return NextResponse.json({ error: `Unsupported method: ${method}` }, { status: 405 })
}
return NextResponse.json(response.data)
} catch (err: unknown) {
return NextResponse.json({ error: (err as Error)?.message || 'Proxy failed' }, { status: 500 })
}
}
+9
View File
@@ -0,0 +1,9 @@
"use client"
import EidolonsInfo from "@/components/eidolonsInfo";
export default function EidolonsInfoPage() {
return (
<div className="w-full">
<EidolonsInfo/>
</div>
);
}
+38
View File
@@ -0,0 +1,38 @@
@import "tailwindcss";
@plugin "daisyui" {
exclude: properties;
themes: winter --default, night --prefersdark, cupcake, coffee;
}
@tailwind utilities;
@plugin 'tailwind-scrollbar' {
nocompatible: true;
}
:root {
--size-big: 4vw;
--size-medium: 3vw;
--size-small: 2vw;
}
::-webkit-scrollbar {
width: 6px;
height: 6px;
}
::-webkit-scrollbar-track {
background: transparent;
}
::-webkit-scrollbar-thumb {
background-color: #9ca3af;
border-radius: 0;
}
::-webkit-scrollbar-button {
display: none;
}
+102
View File
@@ -0,0 +1,102 @@
import type { Metadata } from "next";
import { Geist, Geist_Mono } from "next/font/google";
import "./globals.css";
import Header from "../components/header";
import { ClientThemeWrapper, ThemeProvider } from "@/components/themeController";
import Footer from "@/components/footer";
import { NextIntlClientProvider } from "next-intl";
import { getLocale, getMessages } from "next-intl/server";
import { ToastContainer } from 'react-toastify';
import QueryProviderWrapper from "@/components/queryProvider";
import ClientDataFetcher from "@/components/clientDataFetcher";
import AvatarBar from "@/components/avatarBar";
import ActionBar from "@/components/actionBar";
const geistSans = Geist({
variable: "--font-geist-sans",
subsets: ["latin"],
});
const geistMono = Geist_Mono({
variable: "--font-geist-mono",
subsets: ["latin"],
});
export const metadata: Metadata = {
title: "Firefly SrTools",
description: "SrTools by Firefly Shelter",
icons: {
icon: "/ff-srtool.png",
shortcut: "/ff-srtool.ico",
apple: "/ff-srtool.png",
},
openGraph: {
title: "Firefly SrTools",
description: "SrTools by Firefly Shelter",
url: "https://srtools.punklorde.org",
siteName: "Firefly SrTools",
images: [
{
url: "https://srtools.punklorde.org/ff-srtool.png",
width: 312,
height: 312,
alt: "Firefly SrTools Logo",
},
],
locale: "en_US",
type: "website",
},
twitter: {
card: "summary_large_image",
title: "Firefly SrTools",
description: "SrTools by Firefly Shelter",
images: ["https://srtools.punklorde.org/ff-srtool.png"],
},
};
export default async function RootLayout({
children,
}: Readonly<{
children: React.ReactNode;
}>) {
const messages = await getMessages();
const locale = await getLocale()
return (
<html lang={locale} suppressHydrationWarning>
<body
className={`${geistSans.variable} ${geistMono.variable} antialiased`}
suppressHydrationWarning
>
<NextIntlClientProvider messages={messages}>
<QueryProviderWrapper>
<ThemeProvider>
<ClientThemeWrapper>
<ClientDataFetcher >
<div className="min-h-screen w-full">
<Header />
<div className="grid grid-cols-12 w-full">
<div className="hidden sm:block md:col-span-4 lg:col-span-3 sticky top-0 self-start h-fit">
<AvatarBar />
</div>
<div className="col-span-12 sm:col-span-8 lg:col-span-9">
<ActionBar />
{children}
</div>
</div>
<Footer />
</div>
</ClientDataFetcher>
</ClientThemeWrapper>
</ThemeProvider>
</QueryProviderWrapper>
</NextIntlClientProvider>
<ToastContainer />
</body>
</html>
);
}
+10
View File
@@ -0,0 +1,10 @@
"use client"
import AvatarInfo from "@/components/avatarInfo";
export default function Home() {
return (
<div className="w-full">
<AvatarInfo></AvatarInfo>
</div>
);
}
+11
View File
@@ -0,0 +1,11 @@
"use client";
import RelicsInfo from "@/components/relicsInfo";
export default function RelicsInfoPage() {
return (
<div className="w-full">
<RelicsInfo></RelicsInfo>
</div>
);
}
+11
View File
@@ -0,0 +1,11 @@
"use client"
import ShowCaseInfo from "@/components/showcaseCard"
export default function ShowcaseCard() {
return (
<div>
<ShowCaseInfo />
</div>
)
}
+11
View File
@@ -0,0 +1,11 @@
"use client";
import SkillsInfo from "@/components/skillsInfo";
export default function SkillsInfoPage() {
return (
<div className="w-full">
<SkillsInfo></SkillsInfo>
</div>
);
}