mirror of
https://github.com/skidoodle/erettsegi-browser.git
synced 2026-04-28 13:37:35 +02:00
huge update (pls dont break)
This commit is contained in:
@@ -1,113 +0,0 @@
|
||||
import { type NextRequest, NextResponse } from "next/server";
|
||||
import { subjects } from "@/utils/subjects";
|
||||
|
||||
export async function GET(req: NextRequest) {
|
||||
try {
|
||||
const { searchParams } = req.nextUrl;
|
||||
const vizsgatargy = searchParams.get("vizsgatargy");
|
||||
const ev = searchParams.get("ev");
|
||||
const idoszak = searchParams.get("idoszak");
|
||||
const szint = searchParams.get("szint");
|
||||
|
||||
if (!vizsgatargy && !ev && !idoszak && !szint) {
|
||||
const currentYear = new Date().getFullYear();
|
||||
return NextResponse.json({
|
||||
parameters: {
|
||||
vizsgatargy: {
|
||||
type: "string",
|
||||
required: true,
|
||||
values: subjects.map((s) => ({
|
||||
value: s.value,
|
||||
label: s.label,
|
||||
})),
|
||||
},
|
||||
ev: {
|
||||
type: "integer",
|
||||
required: true,
|
||||
values: `2013 - ${currentYear}`,
|
||||
},
|
||||
idoszak: {
|
||||
type: "string",
|
||||
required: true,
|
||||
values: ["tavasz", "osz"],
|
||||
},
|
||||
szint: {
|
||||
type: "string",
|
||||
required: true,
|
||||
values: ["kozep", "emelt"],
|
||||
},
|
||||
},
|
||||
example:
|
||||
"/api/erettsegi?vizsgatargy=mat&ev=2023&idoszak=tavasz&szint=kozep",
|
||||
});
|
||||
}
|
||||
|
||||
if (!vizsgatargy || !ev || !idoszak || !szint) {
|
||||
const missingParams = [
|
||||
!vizsgatargy && "vizsgatargy",
|
||||
!ev && "ev",
|
||||
!idoszak && "idoszak",
|
||||
!szint && "szint",
|
||||
].filter(Boolean);
|
||||
|
||||
return NextResponse.json(
|
||||
{ error: `Hiányzó paraméterek: ${missingParams.join(", ")}` },
|
||||
{ status: 400 },
|
||||
);
|
||||
}
|
||||
|
||||
if (parseInt(ev, 10) <= 2012) {
|
||||
return NextResponse.json({ error: "Érvénytelen év" }, { status: 400 });
|
||||
}
|
||||
|
||||
const validSubjects = subjects.map((subject) => subject.value);
|
||||
if (!validSubjects.includes(vizsgatargy)) {
|
||||
return NextResponse.json(
|
||||
{ error: "Érvénytelen vizsgatárgy" },
|
||||
{ status: 400 },
|
||||
);
|
||||
}
|
||||
|
||||
const honap = idoszak === "osz" ? "okt" : "maj";
|
||||
const prefix = szint === "emelt" ? `e_${vizsgatargy}` : `k_${vizsgatargy}`;
|
||||
|
||||
const protocol =
|
||||
req.headers.get("x-forwarded-proto") === "https" ? "https" : "http";
|
||||
const host = req.headers.get("host");
|
||||
const baseUrl = `https://dload-oktatas.educatio.hu/erettsegi/feladatok_${ev}${idoszak}_${szint}/`;
|
||||
const proxiedUrl = `${protocol}://${host}/api/proxy?link=${encodeURI(
|
||||
baseUrl,
|
||||
)}`;
|
||||
|
||||
const shortev = ev.slice(-2);
|
||||
const feladat = "fl";
|
||||
const utmutato = "ut";
|
||||
const forras = "for";
|
||||
const megoldas = "meg";
|
||||
|
||||
const urls = {
|
||||
flPdfUrl: `${proxiedUrl}${prefix}_${shortev}${honap}_${feladat}.pdf`,
|
||||
utPdfUrl: `${proxiedUrl}${prefix}_${shortev}${honap}_${utmutato}.pdf`,
|
||||
flZipUrl: ["inf", "infoism", "digkult"].includes(vizsgatargy)
|
||||
? `${baseUrl}${prefix}${forras}_${shortev}${honap}_${feladat}.zip`
|
||||
: undefined,
|
||||
utZipUrl: ["inf", "infoism", "digkult"].includes(vizsgatargy)
|
||||
? `${baseUrl}${prefix}${megoldas}_${shortev}${honap}_${utmutato}.zip`
|
||||
: undefined,
|
||||
flMp3Url: ["angol", "nemet"].includes(vizsgatargy)
|
||||
? `${baseUrl}${prefix}_${shortev}${honap}_${feladat}.mp3`
|
||||
: undefined,
|
||||
};
|
||||
|
||||
return NextResponse.json(urls, {
|
||||
status: 200,
|
||||
headers: { "Cache-Control": "s-maxage=31536000" },
|
||||
});
|
||||
} catch (e: unknown) {
|
||||
console.error("An unexpected error occurred in the API route:", e);
|
||||
return NextResponse.json(
|
||||
{ error: "Internal Server Error" },
|
||||
{ status: 500 },
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -1,68 +0,0 @@
|
||||
import { type NextRequest, NextResponse } from "next/server";
|
||||
|
||||
export async function GET(req: NextRequest) {
|
||||
try {
|
||||
const { searchParams } = req.nextUrl;
|
||||
const link = searchParams.get("link");
|
||||
|
||||
if (!link) {
|
||||
return NextResponse.json({
|
||||
parameters: {
|
||||
link: {
|
||||
type: "string",
|
||||
required: true,
|
||||
},
|
||||
},
|
||||
example: `/api/proxy?link=https://dload-oktatas.educatio.hu/erettsegi/feladatok_2023tavasz_kozep/k_mat_23maj_fl.pdf`,
|
||||
});
|
||||
}
|
||||
|
||||
let url: URL;
|
||||
try {
|
||||
url = new URL(link);
|
||||
} catch {
|
||||
return NextResponse.json(
|
||||
{ error: "Érvénytelen link formátum" },
|
||||
{ status: 400 },
|
||||
);
|
||||
}
|
||||
|
||||
if (url.hostname !== "dload-oktatas.educatio.hu") {
|
||||
return NextResponse.json({ error: "Érvénytelen link" }, { status: 400 });
|
||||
}
|
||||
|
||||
const externalResponse = await fetch(link, {
|
||||
method: "GET",
|
||||
});
|
||||
|
||||
if (!externalResponse.ok) {
|
||||
return NextResponse.json(
|
||||
{ error: "Hiba történt a külső forrás lekérése során." },
|
||||
{ status: externalResponse.status },
|
||||
);
|
||||
}
|
||||
|
||||
const headers = new Headers(externalResponse.headers);
|
||||
headers.set("Cache-Control", "s-maxage=31536000, stale-while-revalidate");
|
||||
|
||||
const contentType = externalResponse.headers.get("content-type");
|
||||
if (contentType === "application/pdf") {
|
||||
const filename = url.pathname.split("/").pop() ?? "document.pdf";
|
||||
headers.set("Content-Disposition", `inline; filename="${filename}"`);
|
||||
}
|
||||
|
||||
return new NextResponse(externalResponse.body, {
|
||||
status: 200,
|
||||
headers,
|
||||
});
|
||||
|
||||
} catch (e: unknown) {
|
||||
console.error("Proxy Error:", e);
|
||||
const errorMessage =
|
||||
e instanceof Error ? e.message : "An unexpected internal error occurred";
|
||||
return NextResponse.json(
|
||||
{ error: "Internal Server Error", message: errorMessage },
|
||||
{ status: 500 },
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -1,61 +0,0 @@
|
||||
import { type NextRequest, NextResponse } from "next/server";
|
||||
|
||||
const ALLOWED_HOSTS = [
|
||||
"localhost:3000",
|
||||
"erettsegi.albert.lol",
|
||||
"dload-oktatas.educatio.hu",
|
||||
];
|
||||
|
||||
export async function GET(req: NextRequest) {
|
||||
try {
|
||||
const { searchParams } = req.nextUrl;
|
||||
let link = searchParams.get("link");
|
||||
|
||||
if (!link) {
|
||||
return NextResponse.json({
|
||||
parameters: {
|
||||
link: {
|
||||
type: "string",
|
||||
required: true,
|
||||
allowed_hosts: ALLOWED_HOSTS,
|
||||
},
|
||||
},
|
||||
example: `/api/validate?link=https://dload-oktatas.educatio.hu/erettsegi/feladatok_2023tavasz_kozep/k_mat_23maj_fl.pdf`,
|
||||
});
|
||||
}
|
||||
|
||||
let url: URL;
|
||||
try {
|
||||
url = new URL(link);
|
||||
} catch {
|
||||
return NextResponse.json(
|
||||
{ error: "Érvénytelen link formátum" },
|
||||
{ status: 400 },
|
||||
);
|
||||
}
|
||||
|
||||
if (url.pathname === "/api/proxy" && url.searchParams.has("link")) {
|
||||
const realTarget = url.searchParams.get("link");
|
||||
if (realTarget) {
|
||||
try {
|
||||
const realUrl = new URL(realTarget);
|
||||
link = realTarget;
|
||||
url = realUrl;
|
||||
} catch {}
|
||||
}
|
||||
}
|
||||
|
||||
if (!ALLOWED_HOSTS.includes(url.host)) {
|
||||
return NextResponse.json({ error: "Érvénytelen link" }, { status: 400 });
|
||||
}
|
||||
|
||||
const response = await fetch(link, {
|
||||
method: "HEAD",
|
||||
});
|
||||
|
||||
return NextResponse.json({ status: response.status }, { status: 200 });
|
||||
} catch (error) {
|
||||
console.error("Validation Error:", error);
|
||||
return NextResponse.json({ error: "Internal Server Error" }, { status: 500 });
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,76 @@
|
||||
import { type NextRequest, NextResponse } from "next/server";
|
||||
import { parseSegments } from "@/utils/edu";
|
||||
import { subjects } from "@/utils/subjects";
|
||||
|
||||
const LABELS = {
|
||||
periods: { tavasz: "Tavasz", osz: "Ősz" } as Record<string, string>,
|
||||
levels: { kozep: "Közép", emelt: "Emelt" } as Record<string, string>,
|
||||
};
|
||||
|
||||
export async function GET(
|
||||
req: NextRequest,
|
||||
{ params }: { params: Promise<{ slug: string[] }> },
|
||||
) {
|
||||
try {
|
||||
const { slug } = await params;
|
||||
const query = parseSegments(slug);
|
||||
|
||||
const { subject, year, period, level } = query;
|
||||
|
||||
const isComplete = subject && year && period && level;
|
||||
|
||||
if (isComplete) {
|
||||
const protocol =
|
||||
req.headers.get("x-forwarded-proto") === "https" ? "https" : "http";
|
||||
const host = req.headers.get("host");
|
||||
|
||||
const proxyBase = `${protocol}://${host}/proxy/${subject.slug}/${year}/${period}/${level}`;
|
||||
const makeLink = (type: string) => `${proxyBase}/${type}`;
|
||||
|
||||
return NextResponse.json({
|
||||
found: true,
|
||||
meta: {
|
||||
subject: subject.label,
|
||||
year,
|
||||
period: LABELS.periods[period] ?? period,
|
||||
level: LABELS.levels[level] ?? level,
|
||||
},
|
||||
links: {
|
||||
flPdfUrl: makeLink("feladat"),
|
||||
utPdfUrl: makeLink("utmutato"),
|
||||
flZipUrl: ["inf", "infoism", "digkult"].includes(subject.value)
|
||||
? makeLink("forras")
|
||||
: undefined,
|
||||
utZipUrl: ["inf", "infoism", "digkult"].includes(subject.value)
|
||||
? makeLink("megoldas")
|
||||
: undefined,
|
||||
flMp3Url: ["angol", "nemet"].includes(subject.value)
|
||||
? makeLink("hang")
|
||||
: undefined,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
const suggestions = {
|
||||
found: false,
|
||||
message: "Missing parameters",
|
||||
currentSelection: {
|
||||
subject: subject?.label || null,
|
||||
year: year || null,
|
||||
period: period ? (LABELS.periods[period] ?? period) : null,
|
||||
level: level ? (LABELS.levels[level] ?? level) : null,
|
||||
},
|
||||
options: {
|
||||
subjects: !subject ? subjects.map((s) => s.slug) : undefined,
|
||||
years: !year ? "2013 - 2024" : undefined,
|
||||
periods: !period ? Object.values(LABELS.periods) : undefined,
|
||||
levels: !level ? Object.values(LABELS.levels) : undefined,
|
||||
},
|
||||
};
|
||||
|
||||
return NextResponse.json(suggestions);
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
return NextResponse.json({ error: "Server Error" }, { status: 500 });
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
import { type NextRequest, NextResponse } from "next/server";
|
||||
import { parseSegments, getExternalUrl, type ResourceSlug } from "@/utils/edu";
|
||||
|
||||
export async function GET(
|
||||
_req: NextRequest,
|
||||
{ params }: { params: Promise<{ slug: string[] }> },
|
||||
) {
|
||||
try {
|
||||
const { slug } = await params;
|
||||
|
||||
const { subject, year, period, level, resourceType } = parseSegments(slug);
|
||||
|
||||
if (!subject || !year || !period || !level || !resourceType) {
|
||||
return NextResponse.json(
|
||||
{ error: "Invalid download link. Missing parameters." },
|
||||
{ status: 400 },
|
||||
);
|
||||
}
|
||||
|
||||
const targetUrl = getExternalUrl(
|
||||
subject.value,
|
||||
year,
|
||||
period,
|
||||
level,
|
||||
resourceType as ResourceSlug,
|
||||
);
|
||||
|
||||
if (!targetUrl) {
|
||||
return NextResponse.json(
|
||||
{ error: "This file type does not exist for this subject." },
|
||||
{ status: 404 },
|
||||
);
|
||||
}
|
||||
|
||||
const externalResponse = await fetch(targetUrl, { method: "GET" });
|
||||
|
||||
if (!externalResponse.ok) {
|
||||
return NextResponse.json(
|
||||
{ error: "File not found on external server." },
|
||||
{ status: 404 },
|
||||
);
|
||||
}
|
||||
|
||||
const headers = new Headers(externalResponse.headers);
|
||||
headers.set("Cache-Control", "s-maxage=31536000, stale-while-revalidate");
|
||||
|
||||
const filename = targetUrl.split("/").pop() ?? "erettsegi_file";
|
||||
headers.set("Content-Disposition", `inline; filename="${filename}"`);
|
||||
|
||||
return new NextResponse(externalResponse.body, { status: 200, headers });
|
||||
} catch (e) {
|
||||
console.error("Proxy Error", e);
|
||||
return NextResponse.json({ error: "Internal Error" }, { status: 500 });
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
import { type NextRequest, NextResponse } from "next/server";
|
||||
import { parseSegments, getExternalUrl, type ResourceSlug } from "@/utils/edu";
|
||||
|
||||
export async function GET(
|
||||
_req: NextRequest,
|
||||
{ params }: { params: Promise<{ slug: string[] }> },
|
||||
) {
|
||||
try {
|
||||
const { slug } = await params;
|
||||
const { subject, year, period, level, resourceType } = parseSegments(slug);
|
||||
|
||||
if (!subject || !year || !period || !level || !resourceType) {
|
||||
return NextResponse.json({ status: 400 });
|
||||
}
|
||||
|
||||
const targetUrl = getExternalUrl(
|
||||
subject.value,
|
||||
year,
|
||||
period,
|
||||
level,
|
||||
resourceType as ResourceSlug,
|
||||
);
|
||||
if (!targetUrl) return NextResponse.json({ status: 404 });
|
||||
|
||||
const res = await fetch(targetUrl, { method: "HEAD" });
|
||||
return NextResponse.json({ status: res.status });
|
||||
} catch {
|
||||
return NextResponse.json({ status: 500 });
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user