Skip to content

Commit

Permalink
feat(pdf): reintroduced pdf utility as a script package
Browse files Browse the repository at this point in the history
  • Loading branch information
marinoandrea committed Feb 29, 2024
1 parent 0161ad2 commit 1aaceef
Show file tree
Hide file tree
Showing 16 changed files with 1,721 additions and 65 deletions.
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,3 +9,4 @@ The following packages are managed via `npm workspaces`:

- `rimun-api`: a tRPC + Express Node application implementing the backend logic.
- `rimun-app`: a React + Vite frontend application for RIMUN's platform and public website.
- `rimun-pdf`: a command line utility for generating RIMUN PDF assets
73 changes: 8 additions & 65 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 3 additions & 0 deletions packages/rimun-pdf/database.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
import { PrismaClient } from "@prisma/client";

export const prisma = new PrismaClient();
130 changes: 130 additions & 0 deletions packages/rimun-pdf/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,130 @@
import * as ftp from "basic-ftp";
import { randomUUID } from "crypto";
import { config as dotenv } from "dotenv";
import workspacesRoot from "find-yarn-workspace-root";
import { mkdir, readFile, rm, writeFile } from "fs/promises";
import { exit } from "process";
import { prisma } from "./database";
import { generateBadges } from "./src";

if (process.env.NODE_ENV === "development") {
const rootDirectory = workspacesRoot();
dotenv({ path: `${rootDirectory}/.env` });
}

const N_BLANK_BADGES_PER_ROLE = 10;

export const ftpConfig = {
host: process.env.FTP_HOST,
user: process.env.FTP_USER,
password: process.env.FTP_PASSWORD,
port: Number.parseInt(process.env.FTP_PORT ?? "21"),
} satisfies ftp.AccessOptions;

async function generate() {
console.log("Generating badges");
console.log("Fetching session info");

const session = await prisma.session.findFirst({
where: { is_active: true },
});

if (!session) {
console.error("No active session in the database.");
exit(1);
}

console.log("Fetching attendee info");
const result = await prisma.personApplication.findMany({
where: {
session: { is_active: true },
status_application: "ACCEPTED",
},
include: {
person: { include: { account: true, country: true } },
school: { include: { country: true } },
delegation: { include: { country: true } },
committee: true,
confirmed_role: true,
confirmed_group: true,
},
});

console.log("Initializing FTP connection");

const ftpClient = new ftp.Client();
await ftpClient.access(ftpConfig as ftp.AccessOptions);

const pictures = new Map<string, string>();

try {
await mkdir("temp");
console.log("Created cache dir 'temp'");
} catch {
console.log("Cache dir 'temp' already exists");
}

console.log("Downloading profile pictures");

let downloaded = 0;

for (const attendee of result) {
const path = attendee.person.picture_path;
const ext = path.split(".")[1];

const tempFileName = `temp/${randomUUID()}.${ext}`;
try {
await ftpClient.downloadTo(tempFileName, path);
pictures.set(path, tempFileName);
} catch {
continue;
} finally {
process.stdout.write(`Downloaded ${++downloaded}/${result.length}\r`);
}
}

let generated = 0;

console.log("Generating badges\n");

const badges = await generateBadges(
result,
session,
async (path) => {
const tempFileName = pictures.get(path);

if (!tempFileName) {
return null;
}

const data = await readFile(tempFileName);

return data;
},
() => {
process.stdout.write(
`Generated ${++generated}/${result.length + N_BLANK_BADGES_PER_ROLE}\r`
);
}
);

ftpClient.close();

try {
await rm("temp", { recursive: true, force: true });
} catch (e) {
console.error(e);
}

const outputFileName = `badges_${new Date().getTime()}.pdf`;

console.log(`Saving badges to file '${outputFileName}'`);

await writeFile(outputFileName, badges);
}

function main() {
generate().catch(console.error);
}

main();
Loading

0 comments on commit 1aaceef

Please sign in to comment.