Skip to content

Commit

Permalink
feat(api): update API route to new app router handlers
Browse files Browse the repository at this point in the history
  • Loading branch information
jacc committed Dec 23, 2024
1 parent 083d34a commit 13d7f56
Show file tree
Hide file tree
Showing 7 changed files with 673 additions and 0 deletions.
125 changes: 125 additions & 0 deletions src/app/api/bug/route.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,125 @@
import { NextRequest, NextResponse } from "next/server";

async function turnstile(token: string, ip: string | null) {
const formData = new URLSearchParams();

formData.append("secret", process.env.TURNSTILE_KEY as string);
formData.append("response", token);

if (ip) {
formData.append("remoteip", ip);
}

const url = "https://challenges.cloudflare.com/turnstile/v0/siteverify";

const result = await fetch(url, {
body: formData,
method: "POST",
});

return (await result.json()) as
| {
success: true;
challenge_ts: string;
hostname: string;
"error-codes": string[];
action: string;
cdata: string;
}
| {
success: false;
"error-codes": [string, ...string[]];
};
}

export async function POST(request: NextRequest) {
try {
const body = await request.json();

const forwardedFor = request.headers.get("x-forwarded-for");
const ip =
forwardedFor?.split(",")[0] ??
request.headers.get("x-real-ip") ??
request.headers.get("cf-connecting-ip") ??
null;

const outcome = await turnstile(body.turnstile, ip);

if (!outcome.success) {
return new NextResponse(null, { status: 400 });
}

const linearResponse = await fetch("https://api.linear.app/graphql", {
method: "POST",
headers: {
"Content-Type": "application/json",
Authorization: `${process.env.LINEAR_API_KEY}`,
},
body: JSON.stringify({
query: `mutation IssueCreate{
issueCreate(
input: {
title: "${body.short}",
description: "**Reported by:** ${body.user.discord_name} (${body.user.discord_id})\\n\\n${body.long}\\n\\nIP: ${ip}",
teamId: "${process.env.LINEAR_TEAM_ID}",
labelIds: ["${process.env.LINEAR_BUG_LABEL}"]
}
) {
success
issue {
id
identifier
title
}
}
}`,
variables: {},
}),
});

if (!linearResponse.ok) {
throw new Error("Failed to create issue in Linear");
}

const parsedLinearResponse = await linearResponse.json();
const identifier = parsedLinearResponse.data.issueCreate.issue.identifier;

await fetch(process.env.FEEDBACK_WEBHOOK as string, {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
content: null,
embeds: [
{
title: `<a:sdvUh:1220462519466852493> New bug report! (${identifier})`,
url: `https://linear.app/stardew/issue/${identifier}`,
color: null,
fields: [
{
name: "What happened?",
value: `${body.short}`,
},
{
name: "What were you doing when this happened?",
value: `${body.long}`,
},
],
author: {
name: `${body.user.discord_name} (${body.user.discord_id})`,
url: "https://cdn.discordapp.com/embed/avatars/0.png",
},
footer: {
text: `Turnstile: ${outcome.challenge_ts} | IP: ${ip}`,
},
},
],
attachments: [],
}),
});

return NextResponse.json({ identifier });
} catch (error: any) {
console.error("Error processing bug report:", error);
return NextResponse.json({ error: error.message }, { status: 500 });
}
}
78 changes: 78 additions & 0 deletions src/app/api/feedback/route.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
import { NextRequest, NextResponse } from "next/server";

async function turnstile(token: string, ip: string | null) {
const formData = new URLSearchParams();

formData.append("secret", process.env.TURNSTILE_KEY as string);
formData.append("response", token);

if (ip) {
formData.append("remoteip", ip);
}

const url = "https://challenges.cloudflare.com/turnstile/v0/siteverify";

const result = await fetch(url, {
body: formData,
method: "POST",
});

return (await result.json()) as
| {
success: true;
challenge_ts: string;
hostname: string;
"error-codes": string[];
action: string;
cdata: string;
}
| {
success: false;
"error-codes": [string, ...string[]];
};
}

export async function POST(request: NextRequest) {
try {
const body = await request.json();

const forwardedFor = request.headers.get("x-forwarded-for");
const ip =
forwardedFor?.split(",")[0] ??
request.headers.get("x-real-ip") ??
request.headers.get("cf-connecting-ip") ??
null;

const outcome = await turnstile(body.turnstile, ip);

if (!outcome.success) {
return new NextResponse(null, { status: 400 });
}

await fetch(process.env.FEEDBACK_WEBHOOK as string, {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
embeds: [
{
author: {
name: `${body.user.discord_name} (${body.user.discord_id})`,
icon_url: body.user.discord_avatar
? `https://cdn.discordapp.com/avatars/${body.user.discord_id}/${body.user.discord_avatar}.png`
: `https://cdn.discordapp.com/embed/avatars/0.png`,
},
title: "<a:SDVowo:1018861004190400513> Feedback recieved!",
description: body.body,
footer: {
text: `Turnstile: ${outcome.challenge_ts} | IP: ${ip}`,
},
},
],
}),
});

return NextResponse.json({});
} catch (error: any) {
return NextResponse.json({ error: error.message }, { status: 500 });
}
}
25 changes: 25 additions & 0 deletions src/app/api/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import * as schema from "$drizzle/schema";
import { db } from "@/db";
import { eq } from "drizzle-orm";
import { NextResponse } from "next/server";
import { type NextRequest } from "next/server";
import { getUID } from "./saves/route";

export async function GET(request: NextRequest) {
try {
const uid = await getUID();
if (!uid) {
return new NextResponse(null, { status: 401 });
}

const [user] = await db
.select()
.from(schema.users)
.where(eq(schema.users.id, uid))
.limit(1);

return NextResponse.json(user);
} catch (error: any) {
return NextResponse.json({ error: error.message }, { status: 500 });
}
}
Loading

0 comments on commit 13d7f56

Please sign in to comment.