mirror of
https://github.com/xCyanGrizzly/DragonsStash.git
synced 2026-05-11 06:11:15 +00:00
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:
105
src/lib/telegram/admin-queries.ts
Normal file
105
src/lib/telegram/admin-queries.ts
Normal file
@@ -0,0 +1,105 @@
|
||||
import { prisma } from "@/lib/prisma";
|
||||
|
||||
// ── Account queries ──
|
||||
|
||||
export async function listAccounts() {
|
||||
const accounts = await prisma.telegramAccount.findMany({
|
||||
orderBy: { createdAt: "desc" },
|
||||
include: {
|
||||
_count: { select: { channelMaps: true, ingestionRuns: true } },
|
||||
},
|
||||
});
|
||||
|
||||
return accounts.map((a) => ({
|
||||
id: a.id,
|
||||
phone: a.phone,
|
||||
displayName: a.displayName,
|
||||
isActive: a.isActive,
|
||||
authState: a.authState,
|
||||
authCode: a.authCode,
|
||||
lastSeenAt: a.lastSeenAt?.toISOString() ?? null,
|
||||
createdAt: a.createdAt.toISOString(),
|
||||
channelCount: a._count.channelMaps,
|
||||
runCount: a._count.ingestionRuns,
|
||||
}));
|
||||
}
|
||||
|
||||
export type AccountRow = Awaited<ReturnType<typeof listAccounts>>[number];
|
||||
|
||||
// ── Channel queries ──
|
||||
|
||||
export async function listChannels() {
|
||||
const channels = await prisma.telegramChannel.findMany({
|
||||
orderBy: { createdAt: "desc" },
|
||||
include: {
|
||||
_count: { select: { accountMaps: true, packages: true } },
|
||||
},
|
||||
});
|
||||
|
||||
return channels.map((c) => ({
|
||||
id: c.id,
|
||||
telegramId: c.telegramId.toString(),
|
||||
title: c.title,
|
||||
type: c.type,
|
||||
isActive: c.isActive,
|
||||
createdAt: c.createdAt.toISOString(),
|
||||
accountCount: c._count.accountMaps,
|
||||
packageCount: c._count.packages,
|
||||
}));
|
||||
}
|
||||
|
||||
export type ChannelRow = Awaited<ReturnType<typeof listChannels>>[number];
|
||||
|
||||
// ── Account-Channel link queries ──
|
||||
|
||||
export async function listAccountChannelLinks(accountId: string) {
|
||||
const links = await prisma.accountChannelMap.findMany({
|
||||
where: { accountId },
|
||||
include: {
|
||||
channel: { select: { id: true, title: true, type: true, telegramId: true } },
|
||||
},
|
||||
orderBy: { createdAt: "desc" },
|
||||
});
|
||||
|
||||
return links.map((l) => ({
|
||||
id: l.id,
|
||||
accountId: l.accountId,
|
||||
channelId: l.channelId,
|
||||
role: l.role,
|
||||
lastProcessedMessageId: l.lastProcessedMessageId?.toString() ?? null,
|
||||
channel: {
|
||||
id: l.channel.id,
|
||||
title: l.channel.title,
|
||||
type: l.channel.type,
|
||||
telegramId: l.channel.telegramId.toString(),
|
||||
},
|
||||
}));
|
||||
}
|
||||
|
||||
export type AccountChannelLinkRow = Awaited<
|
||||
ReturnType<typeof listAccountChannelLinks>
|
||||
>[number];
|
||||
|
||||
export async function getUnlinkedChannels(accountId: string) {
|
||||
const linked = await prisma.accountChannelMap.findMany({
|
||||
where: { accountId },
|
||||
select: { channelId: true },
|
||||
});
|
||||
const linkedIds = linked.map((l) => l.channelId);
|
||||
|
||||
const unlinked = await prisma.telegramChannel.findMany({
|
||||
where: {
|
||||
id: { notIn: linkedIds },
|
||||
isActive: true,
|
||||
},
|
||||
orderBy: { title: "asc" },
|
||||
select: { id: true, title: true, type: true, telegramId: true },
|
||||
});
|
||||
|
||||
return unlinked.map((c) => ({
|
||||
id: c.id,
|
||||
title: c.title,
|
||||
type: c.type,
|
||||
telegramId: c.telegramId.toString(),
|
||||
}));
|
||||
}
|
||||
Reference in New Issue
Block a user