117 lines
3.6 KiB
TypeScript
117 lines
3.6 KiB
TypeScript
import type { ParsedPackageInput, UiSnapshot } from "../shared/types";
|
|
import { sanitizeFilename } from "./utils";
|
|
|
|
export type LinkExportSelection = {
|
|
packages: ParsedPackageInput[];
|
|
packageCount: number;
|
|
linkCount: number;
|
|
defaultFileName: string;
|
|
};
|
|
|
|
function formatTimestampForFileName(date: Date): string {
|
|
const y = date.getFullYear();
|
|
const mo = String(date.getMonth() + 1).padStart(2, "0");
|
|
const d = String(date.getDate()).padStart(2, "0");
|
|
const h = String(date.getHours()).padStart(2, "0");
|
|
const mi = String(date.getMinutes()).padStart(2, "0");
|
|
const s = String(date.getSeconds()).padStart(2, "0");
|
|
return `${y}-${mo}-${d}_${h}-${mi}-${s}`;
|
|
}
|
|
|
|
function buildDefaultFileName(packages: ParsedPackageInput[]): string {
|
|
if (packages.length === 1) {
|
|
const only = packages[0];
|
|
if (only.links.length === 1) {
|
|
const itemName = sanitizeFilename(only.fileNames?.[0] || only.name || "link-export");
|
|
return `${itemName}.txt`;
|
|
}
|
|
return `${sanitizeFilename(only.name || "paket-export")}.txt`;
|
|
}
|
|
return `rd-link-export-${formatTimestampForFileName(new Date())}.txt`;
|
|
}
|
|
|
|
export function buildLinkExportSelection(snapshot: UiSnapshot, packageIds: string[], itemIds: string[]): LinkExportSelection {
|
|
const selectedPackageIds = new Set(packageIds);
|
|
const selectedItemIds = new Set(itemIds);
|
|
const packages: ParsedPackageInput[] = [];
|
|
|
|
for (const packageId of snapshot.session.packageOrder) {
|
|
const pkg = snapshot.session.packages[packageId];
|
|
if (!pkg) {
|
|
continue;
|
|
}
|
|
|
|
const useWholePackage = selectedPackageIds.has(packageId);
|
|
const relevantItemIds = useWholePackage
|
|
? pkg.itemIds
|
|
: pkg.itemIds.filter((itemId) => selectedItemIds.has(itemId));
|
|
|
|
if (relevantItemIds.length === 0) {
|
|
continue;
|
|
}
|
|
|
|
const links: string[] = [];
|
|
const fileNames: string[] = [];
|
|
for (const itemId of relevantItemIds) {
|
|
const item = snapshot.session.items[itemId];
|
|
if (!item || !String(item.url || "").trim()) {
|
|
continue;
|
|
}
|
|
links.push(String(item.url).trim());
|
|
const rawFileName = String(item.fileName || "").trim();
|
|
fileNames.push(rawFileName ? sanitizeFilename(rawFileName) : "");
|
|
}
|
|
|
|
if (links.length === 0) {
|
|
continue;
|
|
}
|
|
|
|
const exportEntry: ParsedPackageInput = {
|
|
name: sanitizeFilename(pkg.name || "Paket"),
|
|
links
|
|
};
|
|
if (fileNames.some((fileName) => fileName.length > 0)) {
|
|
exportEntry.fileNames = fileNames;
|
|
}
|
|
packages.push(exportEntry);
|
|
}
|
|
|
|
const linkCount = packages.reduce((sum, pkg) => sum + pkg.links.length, 0);
|
|
return {
|
|
packages,
|
|
packageCount: packages.length,
|
|
linkCount,
|
|
defaultFileName: buildDefaultFileName(packages)
|
|
};
|
|
}
|
|
|
|
export function serializeLinkExportText(packages: ParsedPackageInput[]): string {
|
|
const lines: string[] = [
|
|
"# rd-link-export: 1",
|
|
"# Re-import in Real-Debrid-Downloader keeps package names and optional file names.",
|
|
""
|
|
];
|
|
|
|
for (const pkg of packages) {
|
|
if (!pkg || !pkg.name || !Array.isArray(pkg.links) || pkg.links.length === 0) {
|
|
continue;
|
|
}
|
|
lines.push(`# package: ${sanitizeFilename(pkg.name)}`);
|
|
for (let index = 0; index < pkg.links.length; index += 1) {
|
|
const link = String(pkg.links[index] || "").trim();
|
|
if (!link) {
|
|
continue;
|
|
}
|
|
const rawFileName = String(pkg.fileNames?.[index] || "").trim();
|
|
const fileName = rawFileName ? sanitizeFilename(rawFileName) : "";
|
|
if (fileName) {
|
|
lines.push(`# file: ${fileName}`);
|
|
}
|
|
lines.push(link);
|
|
}
|
|
lines.push("");
|
|
}
|
|
|
|
return `${lines.join("\n").trim()}\n`;
|
|
}
|