Files
altbin.dev/prisma/altbin.db
T

1540 lines
76 KiB
Plaintext
Raw Normal View History

2025-08-20 17:14:23 +02:00
SQLite format 3@ ŒŒ.zp
2025-08-20 14:14:33 +02:00
ø k
Ö³ k
«=„YtablePastePasteCREATE TABLE "Paste" (
"id" TEXT NOT NULL PRIMARY KEY,
"title" TEXT,
"content" TEXT NOT NULL,
"password" TEXT,
"maxViews" INTEGER,
"views" INTEGER NOT NULL DEFAULT 0,
"size" INTEGER,
"createdAt" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
"createdBy" TEXT
))=indexsqlite_autoindex_Paste_1PasteƒZ11†_table_prisma_migrations_prisma_migrationsCREATE TABLE "_prisma_migrations" (
"id" TEXT PRIMARY KEY NOT NULL,
"checksum" TEXT NOT NULL,
"finished_at" DATETIME,
"migration_name" TEXT NOT NULL,
"logs" TEXT,
"rolled_back_at" DATETIME,
"started_at" DATETIME NOT NULL DEFAULT current_timestamp,
2025-08-20 17:14:23 +02:00
"applied_steps_count" INTEGER UNSIGNED NOT NULL DEFAULT 0
2025-08-20 14:14:33 +02:00
)CW1indexsqlite_autoindex__prisma_migrations_1_prisma_migrations
pp

U
3 f873948d-8cca-42e0-b29f-47a4d55b0c03e5a55fd30fef2e082ffb3d4b286f515a65e3b4b139c55e2d74181d0d36d0d903˜Â‰Ú;20250819133430_init˜Â‰Ú4
ØØ'U f873948d-8cca-42e0-b29f-47a4d55b0c03
import ConfirmDeleteModal from '@/components/ConfirmDeleteModal';
import LogoutButton from '@/components/LogoutButton';
import { Player } from "@lordicon/react";
import { motion } from 'framer-motion';
import { Search } from 'lucide-react';
import { useSession } from 'next-auth/react';
import { useRouter } from 'next/navigation';
import { forwardRef, useEffect, useRef, useState } from "react";
import { toast, Toaster } from 'react-hot-toast';
const PER_PAGE = 6;
const dashboardIcons = {
clipboard: "https://cdn.lordicon.com/gvtjlyjf.json",
views: "https://cdn.lordicon.com/dicvhxpz.json",
calendar: "https://cdn.lordicon.com/uphbloed.json",
code: "https://cdn.lordicon.com/xqdfobxg.json",
storage: "https://cdn.lordicon.com/kikjlzqr.json",
chart: "https://cdn.lordicon.com/abwrkdvl.json",
flame: "https://cdn.lordicon.com/thtrcqvk.json",
file: "https://cdn.lordicon.com/fikcyfpp.json",
};
// --- Loading screen (spinner + skeletons)
function LoadingDashboard() {
const StatSkeleton = () => (
<div className="rounded-2xl bg-[#11131c] p-5 border border-white/10">
<div className="flex items-center gap-3">
<div className="w-10 h-10 rounded-xl bg-white/10 animate-pulse" />
9 ¤%1vwxmq49"use client";
import { useSession } from "next-auth/react";
import { useRouter } from "next/navigation";
import { useCallback, useEffect, useState } from "react";
import Editor from "./paste-form/Editor";
import SidebarPanel from "./paste-form/SidebarPanel";
import AuthSection from "./paste-form/AuthSection";
export default function PasteForm() {
const router = useRouter();
const { data: session } = useSession();
const [title, setTitle] = useState("");
const [content, setContent] = useState("");
const [password, setPassword] = useState("");
const [maxViews, setMaxViews] = useState("");
const [isSaving, setIsSaving] = useState(false);
const [advanced, setAdvanced] = useState(true);
const handleSave = useCallback(async () => {
if (!content.trim()) return;
setIsSaving(true);
const res = await fetch("/api/paste", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
title: title.trim() || null,
content,
password: password || null,
maxViews: maxViews ? parseInt(maxViews, 10) : null,
createdBy: session?.user?.id || null,
}),
});
if (res.ok) {
const data = await res.json();
router.push(`/${data.id}`);
}
setIsSaving(false);
}, [title, content, password, maxViews, session, router]);
// Raccourci clavier Ctrl+S
useEffect(() => {
const onKeyDown = (e: KeyboardEvent) => {
if ((e.ctrlKey || e.metaKey) && e.key.toLowerCase() === "s") {
e.preventDefault();
if (!isSaving && content.trim()) handleSave();
}
};
window.addEventListener("keydown", onKeyDown);
return () => window.removeEventListener("keydown", onKeyDown);
}, [handleSave, isSaving, content]);
return (
<div className="w-screen h-screen bg-[#0e0f13] text-white relative">
<Editor content={content} setContent={setContent} />
<SidebarPanel
title={title}
setTitle={setTitle}
maxViews={maxViews}
setMaxViews={setMaxViews}
password={password}
setPassword={setPassword}
content={content}
2025-08-20 17:14:23 +02:00
isSaving={isSaving}
2025-08-20 16:05:24 +02:00
handleSave={handleSave}
advanced={advanced}
2025-08-20 17:14:23 +02:00
setAdvanced={setAdvanced}
2025-08-20 16:05:24 +02:00
/>
2025-08-20 14:14:33 +02:00
<AuthSection />
< 
 
 
MÝÅY¡}­éeMqõѹ sgmlkmh 5rsf9su qnikg1j
td9mgv7 9itwyk4 jy0sbcs
rsyefjn 68u38u6 hmj3ytp zgql25p 5p95uya yfuxu6a 012n7kb qa65aao
 vwxmq49
ÄÄ9 ¤%1vwxmq49"use client";
import { useSession } from "next-auth/react";
import { useRouter } from "next/navigation";
import { useCallback, useEffect, useState } from "react";
import Editor from "./paste-form/Editor";
import SidebarPanel from "./paste-form/SidebarPanel";
import AuthSection from "./paste-form/AuthSection";
export default function PasteForm() {
const router = useRouter();
const { data: session } = useSession();
const [title, setTitle] = useState("");
const [content, setContent] = useState("");
const [password, setPassword] = useState("");
const [maxViews, setMaxViews] = useState("");
const [isSaving, setIsSaving] = useState(false);
const [advanced, setAdvanced] = useState(true);
const handleSave = useCallback(async () => {
if (!content.trim()) return;
setIsSaving(true);
const res = await fetch("/api/paste", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
title: title.trim() || null,
content,
password: password || null,
maxViews: maxViews ? parseInt(maxViews, 10) : null,
createdBy: session?.user?.id || null,
}),
});
if (res.ok) {
const data = await res.json();
router.push(`/${data.id}`);
}
setIsSaving(false);
}, [title, content, password, maxViews, session, router]);
// Raccourci clavier Ctrl+S
useEffect(() => {
const onKeyDown = (e: KeyboardEvent) => {
if ((e.ctrlKey || e.metaKey) && e.key.toLowerCase() === "s") {
e.preventDefault();
if (!isSaving && content.trim()) handleSave();
}
};
window.addEventListener("keydown", onKeyDown);
return () => window.removeEventListener("keydown", onKeyDown);
}, [handleSave, isSaving, content]);
return (
<div className="w-screen h-screen bg-[#0e0f13] text-white relative">
<Editor content={content} setContent={setContent} />
<SidebarPanel
title={title}
setTitle={setTitle}
maxViews={maxViews}
setMaxViews={setMaxViews}
password={password}
setPassword={setPassword}
2025-08-20 15:16:00 +02:00
content={content}
isSaving={isSaving}
2025-08-20 14:14:33 +02:00
handleSave={handleSave}
advanced={advanced}
2025-08-20 15:16:00 +02:00
setAdvanced={setAdvanced}
/>
<AuthSection />
</div>
);
}
 ˜Ãgàf281113457833672706
mm

*/
export default function PastePage({ params }: { params: { id: st ]1hmj3ytpimport { redirect } from "next/navigation";
export default function RawIndexPage() {
redirect("/");
}h˜Ç€Ó7281113457833672706Ým » 1zgql25p'use client';
import {
CalendarDays,
Copy,
Download,
Eye,
FileText,
Plus,
} from 'lucide-react';
import { useRouter } from 'next/navigation';
import { use, useEffect, useRef, useState } from 'react'; // 👈 import de `use`
import Prism from 'prismjs';
import 'prismjs/components/prism-bash';
import 'prismjs/components/prism-javascript';
import 'prismjs/components/prism-json';
import 'prismjs/components/prism-python';
import 'prismjs/components/prism-typescript';
import 'prismjs/themes/prism-tomorrow.css';
import 'prismjs/plugins/line-numbers/prism-line-numbers.css';
import 'prismjs/plugins/line-numbers/prism-line-numbers.js';
/** ---------- Loader animé (spinner + skeletons) ---------- */
function LoadingPaste() {
return (
<div className="relative w-screen h-screen bg-[#0e0f13] text-white flex overflow-hidden">
{/* Zone code (skeleton lignes) */}
<div className="flex-1 h-full font-mono text-sm">
<div className="h-full overflow-auto pt-6 pb-6 px-6">
<div className="mb-4 flex items-center gap-2">
<div
className="h-5 w-5 rounded-full border-2 border-white/30 border-t-transparent animate-spin"
aria-hidden
/>
<span className="text-white/70 text-sm">Chargement du paste…</span>
</div>
<div className="space-y-2">
{Array.from({ length: 28 }).map((_, i) => (
<div
key={i}
className={`h-3 rounded bg-white/10 animate-pulse ${i % 3 === 0 ? 'w-5/6' : i % 3 === 1 ? 'w-11/12' : 'w-3/4'}`}
/>
))}
</div>
</div>
</div>
{/* Sidebar (skeleton cartes + boutons) */}
<div
className="
absolute top-4 right-4 w-[300px] rounded-2xl p-5 text-sm
backdrop-blur-xl shadow-2xl
bg-[linear-gradient(to_bottom_right,#1a2035,#101522)]
ring-1 ring-white/10 mr-4
"
>
<div className="mb-4">
<div className="flex items-center justify-between">
<div className="h-6 w-24 bg-white/10 rounded animate-pulse" />
<div className="h-7 w-20 rounded-full bg-green-600/60 animate-pulse" />
</div>
<div className="h-4 w-40 bg-white/10 rounded mt-2 animate-pulse" />
</div>
<div className="grid grid-cols-2 gap-3 text-neutral-300">
<div className="flex items-center gap-2 rounded-lg px-3 py-2 bg-[#151b2e] ring-1 ring-white/15">
<div className="h-4 w-4 rounded bg-white/10 animate-pulse" />
<div className="flex-1 space-y-1">
<div className="h-3 w-10 bg-white/10 rounded animate-pulse" />
<div className="h-3 w-12 bg-white/20 rounded animate-pulse" />
</div>
</div>
<div className="flex items-center gap-2 rounded-lg px-3 py-2 bg-[#151b2e] ring-1 ring-white/15">
<div className="h-4 w-4 rounded bg-white/10 animate-pulse" />
<div className="flex-1 space-y-1">
<div className="h-3 w-12 bg-white/10 rounded animate-pulse" />
<div className="h-3 w-16 bg-white/20 rounded animate-pulse" />
</div>
</div>
</div>
<div className="h-px bg-white/10 my-4" />
<div className="grid grid-cols-4 gap-2">
{Array.from({ length: 4 }).map((_, i) => (
<div key={i} className="h-9 rounded-lg bg-[#151b2e] ring-1 ring-white/10 animate-pulse" />
))}
</div>
<div className="mt-3 h-3 w-16 mx-auto bg-green-400/50 rounded animate-pulse" />
</div>
2025-08-20 14:14:33 +02:00
</div>
);
}
/** -------------------------------------------------------- */
export default function PastePage({
params,
}: {
params: Promise<{ id: string }>; // 👈 params est une Promise
}) {
const { id } = use(params); // 👈 on “unwrap†la Promise côté client
2025-08-20 15:16:00 +02:00
2025-08-20 14:14:33 +02:00
const [paste, setPaste] = useState<any | null>(null);
const [error, setError] = useState('');
const [loading, setLoading] = useState(true);
const [language, setLanguage] = useState<string>('language-javascript');
const [copied, setCopied] = useState(false);
const codeRef = useRef<HTMLPreElement | null>(null);
const router = useRouter();
const fetchPaste = async (pwd?: string) => {
setLoading(true);
const res = await fetch(`/api/paste/${id}`, { // 👈 utilise `id`
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ password: pwd || '' }),
});
if (res.status === 403) {
setError('Invalid password.');
setLoading(false);
return;
}
if (res.status === 404) {
setError('Paste not found or expired.');
setLoading(false);
return;
}
const data = await res.json();
setPaste(data);
if (data.content.includes('function') || data.content.includes('const')) {
setLanguage('language-javascript');
} else if (data.content.includes('import') || data.content.includes('export')) {
setLanguage('language-typescript');
2025-08-20 15:16:00 +02:00
} else if (data.content.includes('{') && data.content.includes('}')) {
2025-08-20 14:14:33 +02:00
setLanguage('language-json');
} else {
setLanguage('language-bash');
}
setLoading(false);
};
useEffect(() => {
fetchPaste();
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [id]); // 👈 dépend de `id`
useEffect(() => {
if (paste?.content) {
Prism.highlightAll();
}
}, [paste]);
if (loading) return <LoadingPaste />;
if (error || (paste?.protected && !paste?.content)) {
return (
<div className="h-screen w-screen bg-[#0e0f13] flex items-center justify-center text-white">
<form
onSubmit={(e) => {
e.preventDefault();
fetchPaste((e.currentTarget as any).password.value);
}}
className="
w-full max-w-sm rounded-2xl p-6 space-y-4
backdrop-blur-xl shadow-2xl
bg-[linear-gradient(to_bottom_right,rgba(20,24,38,0.9),rgba(14,16,24,0.9))]
ring-1 ring-white/10
"
>
<h2 className="text-xl font-bold">
<span className="text-red-400">🔒 Protected Paste</span>
</h2>
{error && <p className="text-red-500 text-sm">{error}</p>}
<input
name="password"
type="password"
placeholder="Enter password"
className="
w-full rounded-xl bg-[#0f1320]/60 text-white placeholder:text-neutral-500
px-3 py-2 outline-none
ring-1 ring-white/10 focus:ring-2 focus:ring-blue-500/50
"
/>
<button
type="submit"
className="
w-full inline-flex items-center justify-center gap-2 rounded-xl py-2 text-sm font-medium
bg-gradient-to-b from-[#1b2135] to-[#141a2a] text-white ring-1 ring-white/10
hover:from-[#232a41] hover:to-[#161d2f]
focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-blue-400/60
"
>
View Paste
</button>
</form>
</div>
);
}
return (
<div className="relative w-screen h-screen bg-[#0e0f13] text-white flex overflow-hidden">
<div className="flex-1 h-full font-mono text-sm">
<pre
ref={codeRef}
className="h-full overflow-auto pt-6 pb-6 px-6 line-numbers"
2025-08-20 15:16:00 +02:00
>
<code className={`${language} whitespace-pre-wrap break-words`}>
{paste.content}
</code>
</pre>
</div>
<div
className="
absolute top-4 right-4 w-[300px] rounded-2xl p-5 text-sm
backdrop-blur-xl shadow-2xl
bg-[linear-gradient(to_bottom_right,#1a2035,#101522)]
ring-1 ring-white/10 mr-4
Ým » 15p95uya'use client';
import {
CalendarDays,
Copy,
Download,
Eye,
FileText,
Plus,
} from 'lucide-react';
import { useRouter } from 'next/navigation';
import { use, useEffect, useRef, useState } from 'react'; // 👈 import de `use`
import Prism from 'prismjs';
import 'prismjs/components/prism-bash';
import 'prismjs/components/prism-javascript';
import 'prismjs/components/prism-json';
import 'prismjs/components/prism-python';
import 'prismjs/components/prism-typescript';
import 'prismjs/themes/prism-tomorrow.css';
import 'prismjs/plugins/line-numbers/prism-line-numbers.css';
import 'prismjs/plugins/line-numbers/prism-line-numbers.js';
/** ---------- Loader animé (spinner + skeletons) ---------- */
function LoadingPaste() {
return (
<div className="relative w-screen h-screen bg-[#0e0f13] text-white flex overflow-hidden">
{/* Zone code (skeleton lignes) */}
<div className="flex-1 h-full font-mono text-sm">
<div className="h-full overflow-auto pt-6 pb-6 px-6">
<div className="mb-4 flex items-center gap-2">
<div
className="h-5 w-5 rounded-full border-2 border-white/30 border-t-transparent animate-spin"
aria-hidden
/>
<span className="text-white/70 text-sm">Chargement du paste…</span>
</div>
<div className="space-y-2">
{Array.from({ length: 28 }).map((_, i) => (
<div
key={i}
className={`h-3 rounded bg-white/10 animate-pulse ${i % 3 === 0 ? 'w-5/6' : i % 3 === 1 ? 'w-11/12' : 'w-3/4'}`}
/>
))}
</div>
</div>
</div>
{/* Sidebar (skeleton cartes + boutons) */}
<div
2025-08-20 14:14:33 +02:00
className="
absolute top-4 right-4 w-[300px] rounded-2xl p-5 text-sm
2025-08-20 15:16:00 +02:00
backdrop-blur-xl shadow-2xl
bg-[linear-gradient(to_bottom_right,#1a2035,#101522)]
ring-1 ring-white/10 mr-4
"
>
<div className="mb-4">
<div className="flex items-center justify-between">
<div className="h-6 w-24 bg-white/10 rounded animate-pulse" />
<div className="h-7 w-20 rounded-full bg-green-600/60 animate-pulse" />
</div>
<div className="h-4 w-40 bg-white/10 rounded mt-2 animate-pulse" />
</div>
<div className="grid grid-cols-2 gap-3 text-neutral-300">
<div className="flex items-center gap-2 rounded-lg px-3 py-2 bg-[#151b2e] ring-1 ring-white/15">
2025-08-20 14:14:33 +02:00
<div className="h-4 w-4 rounded bg-white/10 animate-pulse" />
<div className="flex-1 space-y-1">
2025-08-20 15:16:00 +02:00
<div className="h-3 w-10 bg-white/10 rounded animate-pulse" />
<div className="h-3 w-12 bg-white/20 rounded animate-pulse" />
</div>
</div>
<div className="flex items-center gap-2 rounded-lg px-3 py-2 bg-[#151b2e] ring-1 ring-white/15">
2025-08-20 14:14:33 +02:00
<div className="h-4 w-4 rounded bg-white/10 animate-pulse" />
<div className="flex-1 space-y-1">
2025-08-20 15:16:00 +02:00
<div className="h-3 w-12 bg-white/10 rounded animate-pulse" />
<div className="h-3 w-16 bg-white/20 rounded animate-pulse" />
</div>
2025-08-20 14:14:33 +02:00
</div>
</div>
2025-08-20 15:16:00 +02:00
<div className="h-px bg-white/10 my-4" />
2025-08-20 14:14:33 +02:00
2025-08-20 15:16:00 +02:00
<div className="grid grid-cols-4 gap-2">
{Array.from({ length: 4 }).map((_, i) => (
<div key={i} className="h-9 rounded-lg bg-[#151b2e] ring-1 ring-white/10 animate-pulse" />
2025-08-20 16:05:24 +02:00
))}
</div>
<div className="mt-3 h-3 w-16 mx-auto bg-green-400/50 rounded animate-pulse" />
</div>
</div>
);
}
/** -------------------------------------------------------- */
export default function PastePage({
params,
}: {
params: Promise<{ id: string }>
zû·z„:
ˆ'1jy0sbcsgenerator client {
provider = "prisma-client-js"
}
datasource db {
provider = "sqlite"
url = "file:./altbin.db"
}
model Paste {
id String @id @default(cuid())
title String?
content String
password String?
2025-08-20 15:16:00 +02:00
maxViews Int?
views Int @default(0)
size Int?
createdAt DateTime @default(now())
createdBy String?
dummyId String?
dummy Dummy? @relation(fields: [dummyId], references: [id])
}
model Dummy {
id String @id @default(cuid())
pastes Paste[]
} 
˜Ç¤y281113457833672706B
;1rsyefjntechnicien informatique˜Ç‘281113457833672706 «7168u38u6'use client';
import { useRouter } from 'next/navigation';
import Prism from 'prismjs';
import { useEffect, useState } from 'react';
import 'prismjs/components/prism-bash';
import 'prismjs/components/prism-javascript';
import 'prismjs/components/prism-json';
import 'prismjs/components/prism-python';
import 'prismjs/components/prism-typescript';
import 'prismjs/plugins/line-numbers/prism-line-numbers.css';
import 'prismjs/plugins/line-numbers/prism-line-numbers.js';
import 'prismjs/themes/prism-tomorrow.css';
import CodeViewer from '@/components/paste/CodeViewer';
import LoadingPaste from '@/components/paste/LoadingPaste';
import PasswordForm from '@/components/paste/PasswordForm';
import PasteSidebar from '@/components/paste/PasteSidebar';
export default function PastePage({ params }: { params: { id: string } }) {
const { id } = params; // ✅ ici params est direct, pas besoin de use() ni Promise
const router = useRouter();
const [paste, setPaste] = useState<any | null>(null);
const [error, setError] = useState('');
const [loading, setLoading] = useState(true);
const [language, setLanguage] = useState<string>('language-javascript');
const fetchPaste = async (pwd?: string) => {
setLoading(true);
const res = await fetch(`/api/paste/${id}`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ password: pwd || '' }),
});
if (res.status === 403) {
setError('Invalid password.');
setLoading(false);
return;
}
if (res.status === 404) {
setError('Paste not found or expired.');
setLoading(false);
return;
}
2025-08-20 14:14:33 +02:00
const data = await res.json();
setPaste(data);
2025-08-20 15:16:00 +02:00
if (data.content.includes('function') || data.content.includes('const')) {
setLanguage('language-javascript');
2025-08-20 14:14:33 +02:00
} else if (data.content.includes('import') || data.content.includes('export')) {
2025-08-20 15:16:00 +02:00
setLanguage('language-typescript');
} else if (data.content.includes('{') && data.content.includes('}')) {
setLanguage('language-json');
} else {
setLanguage('language-bash');
2025-08-20 14:14:33 +02:00
}
2025-08-20 15:16:00 +02:00
2025-08-20 14:14:33 +02:00
setLoading(false);
2025-08-20 15:16:00 +02:00
};
useEffect(() => {
2025-08-20 14:14:33 +02:00
fetchPaste();
// eslint-disable-next-line react-hooks/exhaustive-deps
2025-08-20 15:16:00 +02:00
}, [id]);
useEffect(() => {
if (paste?.content) {
2025-08-20 14:14:33 +02:00
Prism.highlightAll();
}
2025-08-20 15:16:00 +02:00
}, [paste]);
2025-08-20 16:41:27 +02:00
2025-08-20 16:05:24 +02:00
if (loading) return <LoadingPaste />;
2025-08-20 16:41:27 +02:00
if (error || (paste?.protected && !paste?.content)) {
return <PasswordForm error={error} onSubmit={(pwd) => fetchPaste(pwd)} />;
}
return (
<div className="relative w-screen h-screen bg-[#0e0f13] text-white flex overflow-hidden">
<CodeViewer paste={paste} language={language} />
<PasteSidebar paste={paste} id={id} />
</div>
);
}

՘Nj‹»281113457833672706
e/PasswordForm';
import PasteSidebar from '@/components/paste/PasteSidebar';
export default function PastePage({
params,
}: {
params: Promise<{ id: string }>;
}) {
const { id } = use(params);
const router = useRouter();
const [paste, setPaste] = useState<any | null>(null);
const [error, setError] = useState('');
const [loading, setLoading] = useState(true);
const [language, setLanguage] = useState<string>('language-javascript');
const fetchPaste = async (pwd?: string) => {
setLoading(true);
const res = await fetch(`/api/paste/${id}`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ password: pwd || '' }),
});
if (res.status === 403) {
setError('Invalid password.');
setLoading(false);
return;
}
if (res.status === 404) {
setError('Paste not found or expired.');
set˜g ±15rsf9su'use client';
import { useRouter } from 'next/navigation';
import Prism from 'prismjs';
import { use, useEffect, useState } from 'react';
import 'prismjs/plugins/line-numbers/prism-line-numbers.css';
import 'prismjs/plugins/line-numbers/prism-line-numbers.js';
import 'prismjs/themes/prism-tomorrow.css';
2025-08-20 16:05:24 +02:00
import AuthSection from "@/components/paste-form/AuthSection";
import CodeViewer from '@/components/paste/CodeViewer';
import LoadingPaste from '@/components/paste/LoadingPaste';
2025-08-20 15:16:00 +02:00
import PasswordForm from '@/components/paste/PasswordForm';
2025-08-20 16:05:24 +02:00
import PasteSidebar from '@/components/paste/PasteSidebar';
2025-08-20 15:16:00 +02:00
async function loadLanguage(lang: string) {
try {
await import(`prismjs/components/prism-${lang}.js`);
} catch (err) {
console.warn(`[Prism] Language '${lang}' introuvable. Fallback -> plaintext`);
}
}
2025-08-20 16:05:24 +02:00
2025-08-20 15:16:00 +02:00
export default function PastePage({
params,
}: {
params: Promise<{ id: string }>;
}) {
const { id } = use(params);
const router = useRouter();
const [paste, setPaste] = useState<any | null>(null);
const [error, setError] = useState('');
const [loading, setLoading] = useState(true);
const [language, setLanguage] = useState<string>('language-javascript');
const fetchPaste = async (pwd?: string) => {
setLoading(true);
const res = await fetch(`/api/paste/${id}`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ password: pwd || '' }),
2025-08-20 16:41:27 +02:00
});
if (res.status === 403) {
setError('Invalid password.');
setLoading(false);
return;
}
if (res.status === 404) {
setError('Paste not found or expired.');
setLoading(false);
return;
}
const data = await res.json();
setPaste(data);
2025-08-20 14:14:33 +02:00
2025-08-20 16:41:27 +02:00
const content = data.content.toLowerCase();
2025-08-20 14:14:33 +02:00
2025-08-20 15:16:00 +02:00
let detected = 'javascript';
2025-08-20 16:41:27 +02:00
if (content.includes('select ') || content.includes('insert into')) {
detected = 'sql';
} else if (content.includes('function') || content.includes('const')) {
2025-08-20 15:16:00 +02:00
detected = 'javascript';
2025-08-20 14:14:33 +02:00
} else if (content.includes('import ') || content.includes('export ')) {
detected = 'typescript';
} else if (content.includes('{') && content.includes('}')) {
2025-08-20 15:16:00 +02:00
detected = 'json';
2025-08-20 16:05:24 +02:00
} else if (content.includes('#include') || content.includes('int main')) {
2025-08-20 14:14:33 +02:00
detected = 'cpp';
} else if (content.includes('arduino')) {
2025-08-20 16:41:27 +02:00
detected = 'arduino';
} else {
2025-08-20 14:14:33 +02:00
detected = 'bash';
2025-08-20 15:16:00 +02:00
}
2025-08-20 14:14:33 +02:00
2025-08-20 15:16:00 +02:00
await loadLanguage(detected);
2025-08-20 16:05:24 +02:00
setLanguage(`language-${detected}`);
2025-08-20 15:16:00 +02:00
2025-08-20 14:14:33 +02:00
setLoading(false);
2025-08-20 15:16:00 +02:00
};
2025-08-20 16:05:24 +02:00
useEffect(() => {
fetchPaste();
}, [id]);
useEffect(() => {
if (paste?.content) Prism.highlightAll();
2025-08-20 16:41:27 +02:00
}, [paste, language]);
2025-08-20 14:14:33 +02:00
if (loading) return <LoadingPaste />;
if (error || (paste?.protected && !paste?.content)) {
2025-08-20 15:16:00 +02:00
return <PasswordForm error={error} onSubmit={(pwd) => fetchPaste(pwd)} />;
}
2025-08-20 14:14:33 +02:00
return (
<div className="relative w-screen h-screen bg-[#0e0f13] text-white flex overflow-hidden">
<CodeViewer paste={paste} language={language} />
<PasteSidebar paste={paste} id={id} />
<AuthSection />
</div>
);
}
 :˜ÇÏþ%281113457833672706
¹ý¹ƒN †O1z3hxfmaexport default function PasteViewer({ paste }: { paste: any }) {
return (
<article className="space-y-4">
<h2 className="text-xl font-bold">{paste.title || '(Untitled)'}</h2>
<pre className="bg-neutral-900 p-4 rounded whitespace-pre-wrap break-words">{paste.content}</pre>
<p className="text-sm text-neutral-400">Created: {new Date(paste.createdAt).toLB
;1012n7kbgit push -u origin main˜Çhü281113457833672706˜ ¯31qa65aao'use client';
import { Eye, Lock, Settings } from 'lucide-react';
import { useState } from 'react';
export default function PasteOptionsPanel({
password,
setPassword,
maxViews,
setMaxViews,
onCreate,
disabled,
}: {
password: string;
setPassword: (val: string) => void;
maxViews: string;
setMaxViews: (val: string) => void;
onCreate: () => void;
disabled: boolean;
}) {
const [open, setOpen] = useState(true);
return (
<aside className="w-80 rounded-2xl border border-[#1b1d2a] bg-[#0f111a]/60 shadow-xl p-5 flex flex-col justify-between text-sm backdrop-blur-md">
<div>
<div className="flex justify-between items-center mb-6">
<h2 className="text-lg font-bold text-white">Alt<span className="text-blue-400">Bin</span></h2>
<button
className="bg-green-600 hover:bg-green-500 text-xs font-semibold px-3 py-1 rounded-full"
onClick={onCreate}
disabled={disabled}
>
+ CREATE
</button>
</div>
<button
className="flex items-center gap-2 text-neutral-400 text-xs mb-3"
onClick={() => setOpen(!open)}
>
<Settings size={14} />
Advanced {open ? 'â–¾' : 'â–¸'}
</button>
{open && (
<div className="space-y-6">
<div className="space-y-2">
<label className="flex items-center gap-2 text-neutral-400 text-xs uppercase tracking-wide">
<Eye size={14} /> Max Views
</label>
<input
type="number"
value={maxViews}
onChange={e => setMaxViews(e.target.value)}
placeholder="∞"
className="w-full bg-[#1a1d29] text-white p-2 rounded outline-none"
/>
<p className="text-[11px] text-neutral-500">Delete after X views</p>
</div>
<div className="space-y-2">
<label className="flex items-center gap-2 text-neutral-400 text-xs uppercase tracking-wide">
<Lock size={14} /> Password
</label>
<input
type="password"
value={password}
onChange={e => setPassword(e.target.value)}
placeholder="Optional password"
className="w-full bg-[#1a1d29] text-white p-2 rounded outline-none"
/>
<p className="text-[11px] text-neutral-500">Require password to view</p>
</div>
2025-08-20 15:16:00 +02:00
</div>
)}
</div>
<button
disabled={disabled}
onClick={onCreate}
className={`mt-8 py-2 rounded-md text-sm tracking-wide font-medium flex items-center justify-center ${
disabled
? 'bg-[#1a1d29] text-neutral-500 opacity-50 cursor-not-allowed'
: 'bg-[#1a1d29] text-white hover:bg-neutral-800'
}`}
>
<span className="text-lg">🔒</span> SAVE PASTE
</button>
</aside>
);
} Ó˜Ãl­å281113457833672706
Žh 1yfuxu6aimport { prisma } from '@/lib/prisma';
import bcrypt from 'bcryptjs';
import { NextRequest, NextResponse } from 'next/server';
export const dynamic = 'force-dynamic';
export const revalidate = 0;
export async function POST(
request: NextRequest,
context: { params: Promise<{ id: string }> } // 👈 params est une Promise
) {
const { id: pasteId } = await context.params; // 👈 on attend params
const { password = '' } = await request.json();
if (!pasteId) {
return NextResponse.json({ error: 'Invalid ID' }, { status: 400 });
}
const paste = await prisma.paste.findUnique({ where: { id: pasteId } });
if (!paste) {
return NextResponse.json({ error: 'Not found' }, { status: 404 });
}
if (paste.maxViews !== null && paste.views >= paste.maxViews) {
await prisma.paste.delete({ where: { id: paste.id } });
return NextResponse.json({ error: 'Max views exceeded' }, { status: 404 });
}
if (paste.password) {
const valid = await bcrypt.compare(password, paste.password);
if (!valid) {
return NextResponse.json({ error: 'Invalid password' }, { status: 403 });
}
}
const updated = await prisma.paste.update({
where: { id: paste.id },
data: { views: { increment: 1 } },
select: {
2025-08-20 14:14:33 +02:00
id: true,
2025-08-20 15:16:00 +02:00
title: true,
content: true,
createdAt: true,
views: true,
maxViews: true,
password: true,
},
});
const payload = {
id: updated.id,
title: updated.title,
content: updated.content,
createdAt: updated.createdAt,
views: updated.views,
protected: !!updated.password,
};
if (updated.maxViews !== null && updated.views >= updated.maxViews) {
prisma.paste.delete({ where: { id: updated.id } }).catch(() => {});
}
return NextResponse.json(payload, {
headers: { 'Cache-Control': 'no-store' },
});
}
;˜ÇjiJ281113457833672706 "
>
<div className="mb-4">
<div className="flex items-center justify-between">
<h2 className="text-lg font-bold tracking-tight">
Alt<span className="text-blue-400">Bin</span>
</h2>
<button
onClick={() => router.push('/')}
className="
cursor-pointer inline-flex items-center gap-1 rounded-full px-3 py-1 text-xs font-semibold
bg-green-600 text-white shadow-sm
hover:bg-green-500 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-green-400/60
"
>
<Plus size={14} />
CREATE
</button>
</div>
{paste.title && (
<h1
className="text-sm font-semibold text-blue-300 truncate mt-1"
title={paste.title}
>
{paste.title}
</h1>
)}
</div>
<div className="grid grid-cols-2 gap-3 text-neutral-300">
<div className="flex items-center gap-2 rounded-lg px-3 py-2 bg-[#151b2e] ring-1 ring-white/15">
<Eye size={16} />
<div className="leading-tight">
<div className="text-xs text-neutral-400">Views</div>
<div className="text-sm font-medium text-white">{paste.views}</div>
</div>
</div>
<div className="flex items-center gap-2 rounded-lg px-3 py-2 bg-[#151b2e] ring-1 ring-white/15">
<CalendarDays size={16} />
<div className="leading-tight">
<div className="text-xs text-neutral-400">Created</div>
<div className="text-sm font-medium text-white">
{new Date(paste.createdAt).toLocaleDateString()}
</div>
</div>
</div>
</div>
<div className="h-px bg-white/10 my-4" />
<div className="grid grid-cols-4 gap-2">
<button
onClick={async () => {
await navigator.clipboard.writeText(paste.content);
setCopied(true);
setTimeout(() => setCopied(false), 1200);
}}
className="cursor-pointer inline-flex items-center justify-center rounded-lg p-2 bg-[#151b2e] ring-1 ring-white/10 hover:bg-[#1e253d] hover:ring-blue-400/30"
title="Copy"
>
<Copy size={18} />
</button>
<button
onClick={() => window.open(`/api/${id}?raw=1`, '_blank')} // 👈 utilise `id`
className="cursor-pointer inline-flex items-center justify-center rounded-lg p-2 bg-[#151b2e] ring-1 ring-white/10 hover:bg-[#1e253d] hover:ring-blue-400/30"
title="Raw"
>
<FileText size={18} />
</button>
<button
onClick={() => {
const blob = new Blob([paste.content], { type: 'text/plain' });
const url = URL.createObjectURL(blob);
const a = document.createElement('a');
a.href = url;
a.download = `${id}.txt`; // 👈 utilise `id`
a.click();
URL.revokeObjectURL(url);
}}
className="cursor-pointer inline-flex items-center justify-center rounded-lg p-2 bg-[#151b2e] ring-1 ring-white/10 hover:bg-[#1e253d] hover:ring-blue-400/30"
title="Download"
>
<Download size={18} />
</button>
<button
onClick={() => router.push('/')}
className="cursor-pointer inline-flex items-center justify-center rounded-lg p-2 bg-[#151b2e] ring-1 ring-white/10 hover:bg-[#1e253d] hover:ring-blue-400/30"
title="New paste"
>
<Plus size={18} />
</button>
</div>
<div
className={`mt-3 text-center text-xs transition-opacity ${
copied ? 'opacity-100 text-green-400' : 'opacity-0'
}`}
2025-08-20 14:14:33 +02:00
>
Copied!
2025-08-20 15:16:00 +02:00
</div>
</div>
</div>
);
}
.¿˜Çn281113457833672706; // 👈 params est une Promise
}) {
2025-08-20 14:14:33 +02:00
const { id } = use(params); // 👈 on “unwrap†la Promise côté client
2025-08-20 15:16:00 +02:00
const [paste, setPaste] = useState<any | null>(null);
const [error, setError] = useState('');
const [loading, setLoading] = useState(true);
const [language, setLanguage] = useState<string>('language-javascript');
const [copied, setCopied] = useState(false);
const codeRef = useRef<HTMLPreElement | null>(null);
const router = useRouter();
const fetchPaste = async (pwd?: string) => {
setLoading(true);
const res = await fetch(`/api/paste/${id}`, { // 👈 utilise `id`
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ password: pwd || '' }),
});
if (res.status === 403) {
setError('Invalid password.');
2025-08-20 14:14:33 +02:00
setLoading(false);
2025-08-20 15:16:00 +02:00
return;
2025-08-20 14:14:33 +02:00
}
2025-08-20 15:16:00 +02:00
if (res.status === 404) {
setError('Paste not found or expired.');
2025-08-20 14:14:33 +02:00
setLoading(false);
return;
}
2025-08-20 15:16:00 +02:00
const data = await res.json();
setPaste(data);
2025-08-20 14:14:33 +02:00
if (data.content.includes('function') || data.content.includes('const')) {
2025-08-20 15:16:00 +02:00
setLanguage('language-javascript');
} else if (data.content.includes('import') || data.content.includes('export')) {
2025-08-20 14:14:33 +02:00
setLanguage('language-typescript');
2025-08-20 15:16:00 +02:00
} else if (data.content.includes('{') && data.content.includes('}')) {
2025-08-20 14:14:33 +02:00
setLanguage('language-json');
2025-08-20 15:16:00 +02:00
} else {
2025-08-20 14:14:33 +02:00
setLanguage('language-bash');
2025-08-20 15:16:00 +02:00
}
setLoading(false);
};
useEffect(() => {
fetchPaste();
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [id]); // 👈 dépend de `id`
useEffect(() => {
if (paste?.content) {
Prism.highlightAll();
}
}, [paste]);
if (loading) return <LoadingPaste />;
if (error || (paste?.protected && !paste?.content)) {
2025-08-20 14:14:33 +02:00
return (
2025-08-20 15:16:00 +02:00
<div className="h-screen w-screen bg-[#0e0f13] flex items-center justify-center text-white">
<form
onSubmit={(e) => {
e.preventDefault();
fetchPaste((e.currentTarget as any).password.value);
}}
className="
w-full max-w-sm rounded-2xl p-6 space-y-4
backdrop-blur-xl shadow-2xl
bg-[linear-gradient(to_bottom_right,rgba(20,24,38,0.9),rgba(14,16,24,0.9))]
2025-08-20 14:14:33 +02:00
ring-1 ring-white/10
2025-08-20 15:16:00 +02:00
"
>
<h2 className="text-xl font-bold">
<span className="text-red-400">🔒 Protected Paste</span>
</h2>
{error && <p className="text-red-500 text-sm">{error}</p>}
<input
name="password"
type="password"
placeholder="Enter password"
className="
w-full rounded-xl bg-[#0f1320]/60 text-white placeholder:text-neutral-500
px-3 py-2 outline-none
ring-1 ring-white/10 focus:ring-2 focus:ring-blue-500/50
2025-08-20 14:14:33 +02:00
"
2025-08-20 15:16:00 +02:00
/>
<button
type="submit"
className="
w-full inline-flex items-center justify-center gap-2 rounded-xl py-2 text-sm font-medium
bg-gradient-to-b from-[#1b2135] to-[#141a2a] text-white ring-1 ring-white/10
hover:from-[#232a41] hover:to-[#161d2f]
focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-blue-400/60
"
>
View Paste
2025-08-20 14:14:33 +02:00
</button>
2025-08-20 15:16:00 +02:00
</form>
</div>
);
}
return (
<div className="relative w-screen h-screen bg-[#0e0f13] text-white flex overflow-hidden">
2025-08-20 14:14:33 +02:00
<div className="flex-1 h-full font-mono text-sm">
<pre
ref={codeRef}
className="h-full overflow-auto pt-6 pb-6 px-6 line-numbers"
>
<code className={`${language} whitespace-pre-wrap break-words`}>
{paste.content}
</code>
</pre>
</div>
<div
className="
absolute top-4 right-4 w-[300px] rounded-2xl p-5 text-sm
backdrop-blur-xl shadow-2xl
bg-[linear-gradient(to_bottom_right,#1a2035,#101522)]
ring-1 ring-white/10 mr-4
"
>
<div className="mb-4">
<div className="flex items-center justify-between">
<h2 className="text-lg font-bold tracking-tight">
Alt<span className="text-blue-400">Bin</span>
</h2>
<button
onClick={() => router.push('/')}
className="
cursor-pointer inline-flex items-center gap-1 rounded-full px-3 py-1 text-xs font-semibold
bg-green-600 text-white shadow-sm
hover:bg-green-500 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-green-400/60
"
>
<Plus size={14} />
CREATE
</button>
</div>
{paste.title && (
<h1
className="text-sm font-semibold text-blue-300 truncate mt-1"
title={paste.title}
>
{paste.title}
</h1>
)}
</div>
<div className="grid grid-cols-2 gap-3 text-neutral-300">
<div className="flex items-center gap-2 rounded-lg px-3 py-2 bg-[#151b2e] ring-1 ring-white/15">
<Eye size={16} />
<div className="leading-tight">
<div className="text-xs text-neutral-400">Views</div>
<div className="text-sm font-medium text-white">{paste.views}</div>
</div>
</div>
<div className="flex items-center gap-2 rounded-lg px-3 py-2 bg-[#151b2e] ring-1 ring-white/15">
<CalendarDays size={16} />
<div className="leading-tight">
<div className="text-xs text-neutral-400">Created</div>
<div className="text-sm font-medium text-white">
{new Date(paste.createdAt).toLocaleDateString()}
</div>
</div>
</div>
2025-08-20 15:16:00 +02:00
</div>
2025-08-20 14:14:33 +02:00
<div className="h-px bg-white/10 my-4" />
<div className="grid grid-cols-4 gap-2">
<button
onClick={async () => {
await navigator.clipboard.writeText(paste.content);
setCopied(true);
setTimeout(() => setCopied(false), 1200);
}}
className="cursor-pointer inline-flex items-center justify-center rounded-lg p-2 bg-[#151b2e] ring-1 ring-white/10 hover:bg-[#1e253d] hover:ring-blue-400/30"
title="Copy"
2025-08-20 15:16:00 +02:00
>
2025-08-20 14:14:33 +02:00
<Copy size={18} />
</button>
<button
onClick={() => window.open(`/api/${id}?raw=1`, '_blank')} // 👈 utilise `id`
className="cursor-pointer inline-flex items-center justify-center rounded-lg p-2 bg-[#151b2e] ring-1 ring-white/10 hover:bg-[#1e253d] hover:ring-blue-400/30"
title="Raw"
>
<FileText size={18} />
</button>
<button
onClick={() => {
const blob = new Blob([paste.content], { type: 'text/plain' });
const url = URL.createObjectURL(blob);
const a = document.createElement('a');
a.href = url;
a.download = `${id}.txt`; // 👈 utilise `id`
a.click();
URL.revokeObjectURL(url);
}}
className="cursor-pointer inline-flex items-center justify-center rounded-lg p-2 bg-[#151b2e] ring-1 ring-white/10 hover:bg-[#1e253d] hover:ring-blue-400/30"
title="Download"
>
<Download size={18} />
</button>
<button
onClick={() => router.push('/')}
2025-08-20 16:05:24 +02:00
className="cursor-pointer inline-flex items-center justify-center rounded-lg p-2 bg-[#151b2e] ring-1 ring-white/10 hover:bg-[#1e253d] hover:ring-blue-400/30"
title="New paste"
>
<Plus size={18} />
</button>
</div>
<div
className={`mt-3 text-center text-xs transition-opacity ${
copied ? 'opacity-100 text-green-400' : 'opacity-0'
}`}
>
Copied!
</div>
</div>
</div>
);
}
.¿˜Çx¬c281113457833672706
c
[c…u
1qnikg1j+++++ +++++ initialize counter (cell #0) to 10
[ use loop to set 70/100/30 in cells #1–3
> +++++ ++ add 7 to cell #1
> +++++ +++++ add 10 to cell #2
> +++ add 3 to cell #3
<<< - decrement counter (cell #0)
]
> ++ . print 'H'
> + . print 'e'
+++++ ++ . print 'l'
. print 'l'
+++ . print 'o'
> ++ . print ' '
<< +++++ +++++ +++++ . print 'W'
> +++++ +++++ . print 'o'
+++ . print 'r'
----- - . print 'l'
----- --- . print 'd'
> + . print '!'
ȘÇÅg1281113457833672706…) Š1td9mgv7-- Création d'une table utilisateurs
CREATE TABLE users (
id SERIAL PRIMARY KEY,
username VARCHAR(50) NOT NULL UNIQUE,
email VARCHAR(100) NOT NULL,
created_at TIMESTAMP DEFAULT NOW()
);
-- Insertion de données
INSERT INTO users (username, email)
VALUES
('alice', 'alice@example.com'),
('bob', 'bob@example.com');
-- Sélection de données
SELECT id, username, email
FROM users
WHERE created_at > NOW() - INTERVAL '7 days'
ORDER BY created_at DESC;
-- Mise à jour d'un utilisateur
UPDATE users
SET email = 'alice.new@example.com'
WHERE username = 'alice';
-- Suppression
DELETE FROM users
WHERE username = 'bob';
|˜Ç½Å281113457833672706«n ×19itwyk4'use client';
import { useRouter } from 'next/navigation';
import Prism from 'prismjs';
import { use, useEffect, useState } from 'react';
// === Prism Languages Import ===
import 'prismjs/components/prism-bash';
import 'prismjs/components/prism-c';
import 'prismjs/components/prism-cpp';
import 'prismjs/components/prism-csharp';
import 'prismjs/components/prism-css';
import 'prismjs/components/prism-dart';
import 'prismjs/components/prism-docker';
import 'prismjs/components/prism-go';
import 'prismjs/components/prism-java';
import 'prismjs/components/prism-javascript';
import 'prismjs/components/prism-json';
import 'prismjs/components/prism-kotlin';
import 'prismjs/components/prism-markdown';
import 'prismjs/components/prism-php';
import 'prismjs/components/prism-python';
import 'prismjs/components/prism-ruby';
import 'prismjs/components/prism-rust';
import 'prismjs/components/prism-scala';
import 'prismjs/components/prism-sql';
import 'prismjs/components/prism-swift';
import 'prismjs/components/prism-typescript';
import 'prismjs/components/prism-yaml';
// === Prism Plugins ===
import 'prismjs/plugins/line-numbers/prism-line-numbers.css';
import 'prismjs/plugins/line-numbers/prism-line-numbers.js';
import 'prismjs/themes/prism-tomorrow.css';
// === Components ===
import AuthSection from "@/components/paste-form/AuthSection";
import CodeViewer from '@/components/paste/CodeViewer';
import LoadingPaste from '@/components/paste/LoadingPaste';
import PasswordForm from '@/components/paste/PasswordForm';
import PasteSidebar from '@/components/paste/PasteSidebar';
export default function PastePage({
params,
}: {
params: Promise<{ id: string }>;
}) {
const { id } = use(params);
const router = useRouter();
const [paste, setPaste] = useState<any | null>(null);
const [error, setError] = useState('');
const [loading, setLoading] = useState(true);
const [language, setLanguage] = useState<string>('language-javascript');
const fetchPaste = async (pwd?: string) => {
setLoading(true);
const res = await fetch(`/api/paste/${id}`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ password: pwd || '' }),
});
if (res.status === 403) {
setError('Invalid password.');
setLoading(false);
return;
}
if (res.status === 404) {
setError('Paste not found or expired.');
setLoading(false);
return;
}
const data = await res.json();
setPaste(data);
// === Détection simple du langage ===
const content = data.content || "";
if (content.startsWith('<!DOCTYPE html') || content.startsWith('<html')) {
setLanguage('language-markup'); // HTML/XML
} else if (content.includes('import React') || content.includes('function') || content.includes('const')) {
setLanguage('language-javascript');
} else if (content.includes('export') || content.includes('interface')) {
setLanguage('language-typescript');
} else if (content.includes('class ') && content.includes('public static void main')) {
setLanguage('language-java');
} else if (content.includes('#include') && content.includes('printf')) {
setLanguage('language-c');
} else if (content.includes('std::') || content.includes('cout <<')) {
setLanguage('language-cpp');
} else if (content.includes('using System;')) {
setLanguage('language-csharp');
} else if (content.includes('<?php')) {
setLanguage('language-php');
} else if (content.includes('def ') || content.includes('print(')) {
setLanguage('language-python');
} else if (content.includes('fn main()') || content.includes('let mut')) {
setLanguage('language-rust');
} else if (content.includes('func main()') || content.includes('package main')) {
setLanguage('language-go');
} else if (content.includes('puts ') || content.includes('end')) {
setLanguage('language-ruby');
} else if (content.toLowerCase().includes('select ') || content.toLowerCase().includes('insert into')) {
setLanguage('language-sql');
} else if (content.startsWith('# ') || content.includes('```')) {
setLanguage('language-markdown');
} else if (content.includes(': ') && !content.includes(';') && content.includes('\n')) {
setLanguage('language-yaml');
} else if (content.includes('val ') || content.includes('object ')) {
setLanguage('language-scala');
} else if (content.includes('fun main()') && content.includes('val ')) {
setLanguage('language-kotlin');
} else if (content.includes('import Foundation') || content.includes('func ')) {
setLanguage('language-swift');
} else if (content.toLowerCase().includes('from ') && content.toLowerCase().includes('docker')) {
setLanguage('language-docker');
} else {
setLanguage('language-bash'); // fallback
}
setLoading(false);
};
useEffect(() => {
fetchPaste();
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [id]);
2025-08-20 17:14:23 +02:00
useEffect(() => {
if (paste?.content) {
Prism.highlightAll();
}
}, [paste]);
if (loading) return <LoadingPaste />;
if (error || (paste?.protected && !paste?.content)) {
return <PasswordForm error={error} onSubmit={(pwd) => fetchPaste(pwd)} />;
}
return (
<div className="relative w-screen h-screen bg-[#0e0f13] text-white flex overflow-hidden">
<CodeViewer paste={paste} language={language} />
<PasteSidebar paste={paste} id={id} />
<AuthSection />
</div>
);
}
Á˜Ç©4 281113457833672706
²²K  K 1sgmlkmh╭─ ï…¼  Dans ï¼ ~/Bureau/altbin.dev  sur ï„“  main !6 ?1 ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────── à 17:08:49  
╰─ pnpm build
> altbin.dev@0.1.0 build /home/ultralion/Bureau/altbin.dev
> next build
â–² Next.js 15.4.6
- Environments: .env
Creating an optimized production build ...
✓ Compiled successfully in 2000ms
✓ Linting and checking validity of types
✓ Collecting page data
✓ Generating static pages (10/10)
✓ Collecting build traces
✓ Finalizing page optimization
Route (app) Size First Load JS
┌ ○ / 3.92 kB 125 kB