mirror of
https://github.com/severian-dev/sucker.severian.dev.git
synced 2025-10-27 20:25:47 +00:00
chore: remove boilerplate shit
This commit is contained in:
3
README.md
Normal file
3
README.md
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
# Sucker
|
||||||
|
|
||||||
|
Check package.json for commands, I can't be bothered.
|
||||||
4
package-lock.json
generated
4
package-lock.json
generated
@@ -1,11 +1,11 @@
|
|||||||
{
|
{
|
||||||
"name": "request-interceptor",
|
"name": "sucker",
|
||||||
"version": "0.1.0",
|
"version": "0.1.0",
|
||||||
"lockfileVersion": 3,
|
"lockfileVersion": 3,
|
||||||
"requires": true,
|
"requires": true,
|
||||||
"packages": {
|
"packages": {
|
||||||
"": {
|
"": {
|
||||||
"name": "request-interceptor",
|
"name": "sucker",
|
||||||
"version": "0.1.0",
|
"version": "0.1.0",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@radix-ui/react-accordion": "^1.2.2",
|
"@radix-ui/react-accordion": "^1.2.2",
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import { NextResponse } from 'next/server';
|
import { NextResponse } from "next/server";
|
||||||
import type { NextRequest } from 'next/server';
|
import type { NextRequest } from "next/server";
|
||||||
|
|
||||||
interface StoredCard extends CardData {
|
interface StoredCard extends CardData {
|
||||||
timestamp: number;
|
timestamp: number;
|
||||||
@@ -15,7 +15,9 @@ function generateId(): string {
|
|||||||
|
|
||||||
function cleanupExpiredCards() {
|
function cleanupExpiredCards() {
|
||||||
const now = Date.now();
|
const now = Date.now();
|
||||||
extractedCards = extractedCards.filter(card => (now - card.timestamp) < EXPIRY_TIME);
|
extractedCards = extractedCards.filter(
|
||||||
|
(card) => now - card.timestamp < EXPIRY_TIME
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
interface Message {
|
interface Message {
|
||||||
@@ -34,16 +36,18 @@ interface CardData {
|
|||||||
function extractPersonaName(content: string, personaIndex: number = 0): string {
|
function extractPersonaName(content: string, personaIndex: number = 0): string {
|
||||||
const personaMatches = Array.from(content.matchAll(/'s Persona:/g));
|
const personaMatches = Array.from(content.matchAll(/'s Persona:/g));
|
||||||
if (personaMatches.length <= personaIndex) return "";
|
if (personaMatches.length <= personaIndex) return "";
|
||||||
|
|
||||||
const personaIdx = personaMatches[personaIndex].index!;
|
const personaIdx = personaMatches[personaIndex].index!;
|
||||||
const lineStartIdx = content.lastIndexOf('\n', personaIdx);
|
const lineStartIdx = content.lastIndexOf("\n", personaIdx);
|
||||||
const lineEndIdx = personaIdx;
|
const lineEndIdx = personaIdx;
|
||||||
|
|
||||||
return content.slice(lineStartIdx === -1 ? 0 : lineStartIdx + 1, lineEndIdx).trim();
|
return content
|
||||||
|
.slice(lineStartIdx === -1 ? 0 : lineStartIdx + 1, lineEndIdx)
|
||||||
|
.trim();
|
||||||
}
|
}
|
||||||
|
|
||||||
function safeReplace(text: string, old: string, newStr: string): string {
|
function safeReplace(text: string, old: string, newStr: string): string {
|
||||||
return old ? text.replace(new RegExp(old, 'g'), newStr) : text;
|
return old ? text.replace(new RegExp(old, "g"), newStr) : text;
|
||||||
}
|
}
|
||||||
|
|
||||||
function extractCardData(messages: Message[]): CardData {
|
function extractCardData(messages: Message[]): CardData {
|
||||||
@@ -60,7 +64,7 @@ function extractCardData(messages: Message[]): CardData {
|
|||||||
scenario: "",
|
scenario: "",
|
||||||
mes_example: "",
|
mes_example: "",
|
||||||
personality: "",
|
personality: "",
|
||||||
first_mes: content1
|
first_mes: content1,
|
||||||
};
|
};
|
||||||
|
|
||||||
if (personaMatches.length >= 2) {
|
if (personaMatches.length >= 2) {
|
||||||
@@ -80,27 +84,32 @@ function extractCardData(messages: Message[]): CardData {
|
|||||||
if (scenarioMarker) {
|
if (scenarioMarker) {
|
||||||
const scenarioStart = scenarioMarker.index! + scenarioMarker[0].length;
|
const scenarioStart = scenarioMarker.index! + scenarioMarker[0].length;
|
||||||
const scenarioRemaining = remaining.slice(scenarioStart);
|
const scenarioRemaining = remaining.slice(scenarioStart);
|
||||||
const exampleInScenarioMarker = scenarioRemaining.match(/Example conversations between/);
|
const exampleInScenarioMarker = scenarioRemaining.match(
|
||||||
const scenarioEnd = exampleInScenarioMarker ? exampleInScenarioMarker.index! : scenarioRemaining.length;
|
/Example conversations between/
|
||||||
|
);
|
||||||
|
const scenarioEnd = exampleInScenarioMarker
|
||||||
|
? exampleInScenarioMarker.index!
|
||||||
|
: scenarioRemaining.length;
|
||||||
cardData.scenario = scenarioRemaining.slice(0, scenarioEnd).trim();
|
cardData.scenario = scenarioRemaining.slice(0, scenarioEnd).trim();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (exampleMarker) {
|
if (exampleMarker) {
|
||||||
const exampleStart = exampleMarker.index!;
|
const exampleStart = exampleMarker.index!;
|
||||||
const rawExampleStr = remaining.slice(exampleStart).trim();
|
const rawExampleStr = remaining.slice(exampleStart).trim();
|
||||||
const colonIdx = rawExampleStr.indexOf(':');
|
const colonIdx = rawExampleStr.indexOf(":");
|
||||||
cardData.mes_example = colonIdx !== -1 ?
|
cardData.mes_example =
|
||||||
rawExampleStr.slice(colonIdx + 1).trim() :
|
colonIdx !== -1
|
||||||
rawExampleStr.trim();
|
? rawExampleStr.slice(colonIdx + 1).trim()
|
||||||
|
: rawExampleStr.trim();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (const field in cardData) {
|
for (const field in cardData) {
|
||||||
if (field !== 'name') {
|
if (field !== "name") {
|
||||||
const val = cardData[field as keyof CardData];
|
const val = cardData[field as keyof CardData];
|
||||||
if (typeof val === 'string') {
|
if (typeof val === "string") {
|
||||||
let newVal = safeReplace(val, userName, '{{user}}');
|
let newVal = safeReplace(val, userName, "{{user}}");
|
||||||
newVal = safeReplace(newVal, charName, '{{char}}');
|
newVal = safeReplace(newVal, charName, "{{char}}");
|
||||||
cardData[field as keyof CardData] = newVal;
|
cardData[field as keyof CardData] = newVal;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -110,27 +119,27 @@ function extractCardData(messages: Message[]): CardData {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export async function POST(request: NextRequest) {
|
export async function POST(request: NextRequest) {
|
||||||
if (request.method === 'OPTIONS') {
|
if (request.method === "OPTIONS") {
|
||||||
return new NextResponse(null, {
|
return new NextResponse(null, {
|
||||||
status: 204,
|
status: 204,
|
||||||
headers: {
|
headers: {
|
||||||
'Access-Control-Allow-Origin': '*',
|
"Access-Control-Allow-Origin": "*",
|
||||||
'Access-Control-Allow-Methods': 'POST, OPTIONS, GET',
|
"Access-Control-Allow-Methods": "POST, OPTIONS, GET",
|
||||||
'Access-Control-Allow-Headers': 'Content-Type, Authorization',
|
"Access-Control-Allow-Headers": "Content-Type, Authorization",
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const body = await request.json();
|
const body = await request.json();
|
||||||
|
|
||||||
if (!body.messages || body.messages.length < 2) {
|
if (!body.messages || body.messages.length < 2) {
|
||||||
return NextResponse.json(
|
return NextResponse.json(
|
||||||
{ error: "Missing messages or insufficient message count" },
|
{ error: "Missing messages or insufficient message count" },
|
||||||
{
|
{
|
||||||
status: 400,
|
status: 400,
|
||||||
headers: {
|
headers: {
|
||||||
'Access-Control-Allow-Origin': '*',
|
"Access-Control-Allow-Origin": "*",
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
@@ -140,25 +149,27 @@ export async function POST(request: NextRequest) {
|
|||||||
extractedCards.push({
|
extractedCards.push({
|
||||||
...cardData,
|
...cardData,
|
||||||
timestamp: Date.now(),
|
timestamp: Date.now(),
|
||||||
id: generateId()
|
id: generateId(),
|
||||||
});
|
});
|
||||||
|
|
||||||
cleanupExpiredCards();
|
cleanupExpiredCards();
|
||||||
|
|
||||||
return NextResponse.json({ status: "Card stored successfully" }, {
|
return NextResponse.json(
|
||||||
headers: {
|
{ status: "Card stored successfully" },
|
||||||
'Access-Control-Allow-Origin': '*',
|
{
|
||||||
},
|
headers: {
|
||||||
});
|
"Access-Control-Allow-Origin": "*",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Error processing request:', error);
|
console.error("Error processing request:", error);
|
||||||
return NextResponse.json(
|
return NextResponse.json(
|
||||||
{ error: "Internal server error" },
|
{ error: "Internal server error" },
|
||||||
{
|
{
|
||||||
status: 500,
|
status: 500,
|
||||||
headers: {
|
headers: {
|
||||||
'Access-Control-Allow-Origin': '*',
|
"Access-Control-Allow-Origin": "*",
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
@@ -167,24 +178,27 @@ export async function POST(request: NextRequest) {
|
|||||||
|
|
||||||
export async function GET() {
|
export async function GET() {
|
||||||
cleanupExpiredCards();
|
cleanupExpiredCards();
|
||||||
|
|
||||||
return NextResponse.json({
|
return NextResponse.json(
|
||||||
status: "online",
|
{
|
||||||
cards: extractedCards.map(({ timestamp, ...card }) => card) // Keep ID but remove timestamp
|
status: "online",
|
||||||
}, {
|
cards: extractedCards.map(({ timestamp, ...card }) => card),
|
||||||
headers: {
|
|
||||||
'Access-Control-Allow-Origin': '*',
|
|
||||||
},
|
},
|
||||||
});
|
{
|
||||||
|
headers: {
|
||||||
|
"Access-Control-Allow-Origin": "*",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function OPTIONS() {
|
export async function OPTIONS() {
|
||||||
return new NextResponse(null, {
|
return new NextResponse(null, {
|
||||||
status: 204,
|
status: 204,
|
||||||
headers: {
|
headers: {
|
||||||
'Access-Control-Allow-Origin': '*',
|
"Access-Control-Allow-Origin": "*",
|
||||||
'Access-Control-Allow-Methods': 'POST, OPTIONS, GET',
|
"Access-Control-Allow-Methods": "POST, OPTIONS, GET",
|
||||||
'Access-Control-Allow-Headers': 'Content-Type, Authorization',
|
"Access-Control-Allow-Headers": "Content-Type, Authorization",
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -91,7 +91,6 @@ export default function Home() {
|
|||||||
if (!card.avatarUrl) return;
|
if (!card.avatarUrl) return;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
// Use proxy directly instead of attempting CORS
|
|
||||||
const img = new Image();
|
const img = new Image();
|
||||||
img.src = `/api/proxy/image?url=${encodeURIComponent(card.avatarUrl)}`;
|
img.src = `/api/proxy/image?url=${encodeURIComponent(card.avatarUrl)}`;
|
||||||
|
|
||||||
@@ -100,14 +99,12 @@ export default function Home() {
|
|||||||
img.onerror = reject;
|
img.onerror = reject;
|
||||||
});
|
});
|
||||||
|
|
||||||
// Create a canvas to convert WebP to PNG
|
|
||||||
const canvas = document.createElement("canvas");
|
const canvas = document.createElement("canvas");
|
||||||
canvas.width = img.width;
|
canvas.width = img.width;
|
||||||
canvas.height = img.height;
|
canvas.height = img.height;
|
||||||
const ctx = canvas.getContext("2d");
|
const ctx = canvas.getContext("2d");
|
||||||
if (!ctx) throw new Error("Could not get canvas context");
|
if (!ctx) throw new Error("Could not get canvas context");
|
||||||
|
|
||||||
// Draw the image and convert to PNG
|
|
||||||
ctx.drawImage(img, 0, 0);
|
ctx.drawImage(img, 0, 0);
|
||||||
const pngBlob = await new Promise<Blob>((resolve) => {
|
const pngBlob = await new Promise<Blob>((resolve) => {
|
||||||
canvas.toBlob((blob) => {
|
canvas.toBlob((blob) => {
|
||||||
@@ -116,10 +113,8 @@ export default function Home() {
|
|||||||
}, "image/png");
|
}, "image/png");
|
||||||
});
|
});
|
||||||
|
|
||||||
// Convert blob to array buffer for PNG embedding
|
|
||||||
const arrayBuffer = await pngBlob.arrayBuffer();
|
const arrayBuffer = await pngBlob.arrayBuffer();
|
||||||
|
|
||||||
// Prepare card data for embedding
|
|
||||||
const cardData = JSON.stringify({
|
const cardData = JSON.stringify({
|
||||||
name: card.name,
|
name: card.name,
|
||||||
first_mes: card.first_mes,
|
first_mes: card.first_mes,
|
||||||
@@ -129,7 +124,6 @@ export default function Home() {
|
|||||||
scenario: card.scenario,
|
scenario: card.scenario,
|
||||||
});
|
});
|
||||||
|
|
||||||
// Generate PNG with embedded card data
|
|
||||||
const newImageData = Png.Generate(arrayBuffer, cardData);
|
const newImageData = Png.Generate(arrayBuffer, cardData);
|
||||||
const newFileName = `${
|
const newFileName = `${
|
||||||
card.name.replace(/\s+/g, "_") || "character"
|
card.name.replace(/\s+/g, "_") || "character"
|
||||||
@@ -138,14 +132,12 @@ export default function Home() {
|
|||||||
type: "image/png",
|
type: "image/png",
|
||||||
});
|
});
|
||||||
|
|
||||||
// Download the file
|
|
||||||
const link = URL.createObjectURL(newFile);
|
const link = URL.createObjectURL(newFile);
|
||||||
const a = document.createElement("a");
|
const a = document.createElement("a");
|
||||||
a.download = newFileName;
|
a.download = newFileName;
|
||||||
a.href = link;
|
a.href = link;
|
||||||
a.click();
|
a.click();
|
||||||
|
|
||||||
// Cleanup
|
|
||||||
URL.revokeObjectURL(link);
|
URL.revokeObjectURL(link);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error("Error generating PNG:", error);
|
console.error("Error generating PNG:", error);
|
||||||
|
|||||||
@@ -1,19 +1,13 @@
|
|||||||
#!/usr/bin/env node
|
#!/usr/bin/env node
|
||||||
const { execSync } = require("child_process");
|
const { execSync } = require("child_process");
|
||||||
|
|
||||||
// 1. Grab the port from the '-p' argument
|
|
||||||
const portIndex = process.argv.indexOf("-p");
|
const portIndex = process.argv.indexOf("-p");
|
||||||
let port = "3000";
|
let port = "3000";
|
||||||
if (portIndex !== -1 && portIndex + 1 < process.argv.length) {
|
if (portIndex !== -1 && portIndex + 1 < process.argv.length) {
|
||||||
port = process.argv[portIndex + 1];
|
port = process.argv[portIndex + 1];
|
||||||
}
|
}
|
||||||
|
|
||||||
// 2. Start Next.js using that port
|
|
||||||
try {
|
try {
|
||||||
// Either pass it directly to next, e.g.:
|
|
||||||
// execSync(`npx next start -p ${port}`, { stdio: "inherit" });
|
|
||||||
//
|
|
||||||
// Or set the PORT env var and run your npm script:
|
|
||||||
execSync(`PORT=${port} npm run start`, { stdio: "inherit" });
|
execSync(`PORT=${port} npm run start`, { stdio: "inherit" });
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.error("Failed to start Next.js:", err);
|
console.error("Failed to start Next.js:", err);
|
||||||
|
|||||||
Reference in New Issue
Block a user