feat: add Telegram integration with forum topic support and creator tracking

Adds full Telegram ZIP ingestion pipeline: TDLib worker service scans source
channels for archive files, deduplicates by content hash, extracts metadata,
uploads to archive channel, and indexes in Postgres. Forum supergroups are
scanned per-topic with topic names used as creator. Filename-based creator
extraction (e.g. "Mammoth Factory - 2026-01.zip") serves as fallback.

Includes admin UI for managing accounts/channels, simplified account setup
(API credentials via env vars), auth code/password submission dialog,
package browser with creator column, and live ingestion activity tracking.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
xCyanGrizzly
2026-02-24 16:02:06 +01:00
parent beb9cfb312
commit b427193d17
70 changed files with 8627 additions and 2 deletions

View File

@@ -0,0 +1,50 @@
import { auth } from "@/lib/auth";
import { redirect } from "next/navigation";
import { listPackages, searchPackages, getIngestionStatus } from "@/lib/telegram/queries";
import { StlTable } from "./_components/stl-table";
interface Props {
searchParams: Promise<Record<string, string | string[] | undefined>>;
}
export default async function StlFilesPage({ searchParams }: Props) {
const session = await auth();
if (!session?.user?.id) redirect("/login");
const params = await searchParams;
const page = Number(params.page) || 1;
const perPage = Number(params.perPage) || 20;
const sort = (params.sort as string) ?? "indexedAt";
const order = (params.order as "asc" | "desc") ?? "desc";
const search = (params.search as string) ?? "";
const creator = (params.creator as string) || undefined;
// Fetch packages and ingestion status in parallel
const [result, ingestionStatus] = await Promise.all([
search
? searchPackages({
query: search,
page,
limit: perPage,
searchIn: "both",
})
: listPackages({
page,
limit: perPage,
creator,
sortBy: sort as "indexedAt" | "fileName" | "fileSize",
order,
}),
getIngestionStatus(),
]);
return (
<StlTable
data={result.items}
pageCount={result.pagination.totalPages}
totalCount={result.pagination.total}
ingestionStatus={ingestionStatus}
/>
);
}