Skip to content

Commit

Permalink
refactor: use express instead of fastify
Browse files Browse the repository at this point in the history
  • Loading branch information
Myphz committed Jan 2, 2024
1 parent c83dfca commit 6aed3b8
Show file tree
Hide file tree
Showing 8 changed files with 755 additions and 734 deletions.
1,244 changes: 627 additions & 617 deletions package-lock.json

Large diffs are not rendered by default.

13 changes: 8 additions & 5 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,15 +7,18 @@
"generate-types": "npx supabase gen types typescript --project-id 'osbnntqdwcamhqbpdzwz' --schema public > src/types/supabase.ts"
},
"dependencies": {
"@fastify/cors": "^8.4.0",
"@fastify/multipart": "^7.7.3",
"@supabase/supabase-js": "^2.36.0",
"fastify": "^4.22.2",
"node-telegram-bot-api": "^0.64.0",
"dotenv": "^16.3.1"
"@types/cors": "^2.8.17",
"cors": "^2.8.5",
"dotenv": "^16.3.1",
"express": "^4.18.2",
"multer": "^1.4.5-lts.1",
"node-telegram-bot-api": "^0.64.0"
},
"devDependencies": {
"@types/express": "^4.17.21",
"@types/jsonwebtoken": "^9.0.3",
"@types/multer": "^1.4.11",
"@types/node": "^20.5.9",
"@types/node-telegram-bot-api": "^0.64.1",
"@typescript-eslint/eslint-plugin": "^6.6.0",
Expand Down
3 changes: 0 additions & 3 deletions src/constants.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,9 @@
import dotenv from "dotenv";
import Fastify from "fastify";
import { throwError } from "./utils/throw";

dotenv.config();
dotenv.config({ path: ".env.production" });

export const fastify = Fastify({ logger: true });

export const TRIPS_BOT_API_TOKEN = process.env.TRIPS_BOT_API_TOKEN ?? throwError("Telegram API Token not set!");
export const CHAT_ID = process.env.CHAT_ID ?? throwError("CHAT_ID not set!");
export const PEXELS_API_KEY =
Expand Down
44 changes: 26 additions & 18 deletions src/main.ts
Original file line number Diff line number Diff line change
@@ -1,24 +1,32 @@
import { fastify } from "./constants";
import express from "express";
import cors from "cors";
import { FilesAPI } from "./routes/files";
import { PexelsAPI } from "./routes/pexels";

import cors from "@fastify/cors";
const app = express();
const PORT = process.env.PORT ? parseInt(process.env.PORT) : 8080;

fastify.register(cors, {
origin: ["http://localhost:5173", "http://localhost", "https://localhost", "capacitor://localhost"],
app.use(
cors({
origin: ["http://localhost:5173", "http://localhost", "https://localhost", "capacitor://localhost"],
}),
);

app.use(FilesAPI);
app.use(PexelsAPI);

const server = app.listen(PORT, () => {
console.log(`Server listening on port ${PORT}`);
});
fastify.register(FilesAPI);
fastify.register(PexelsAPI);

const main = async () => {
try {
await fastify.listen({
host: "0.0.0.0",
port: process.env.PORT ? parseInt(process.env.PORT) : 8080,
});
} catch (err) {
fastify.log.error(err);
process.exit(1);
}
};
main();
// Optional: Handle errors and clean up resources
server.on("error", (error) => {
console.error("Server error:", error);
});

process.on("SIGINT", () => {
server.close(() => {
console.log("Server closed");
process.exit(0);
});
});
107 changes: 59 additions & 48 deletions src/routes/files.ts
Original file line number Diff line number Diff line change
@@ -1,49 +1,60 @@
import { FastifyPluginCallback } from "fastify";
import multipart from "@fastify/multipart";
import express, { Request, Response } from "express";
import multer from "multer";
import { getFileDownload, getFileLink, uploadFiles } from "../telegram";
import { filesGeneratorToArray } from "../utils/array";

export const FilesAPI: FastifyPluginCallback = async (fastify, _, done) => {
await fastify.register(multipart, {
limits: {
fieldNameSize: 1000,
fileSize: 5e6, // 5 MB
files: 50,
fields: 0,
},
});

fastify.post("/upload", async (req, res) => {
console.log("Loading files...");
const files = await filesGeneratorToArray(req.files());
console.log(`Start upload of ${files.length} files...`);
const ret = await uploadFiles(files);

res.code(201);
return ret;
});

fastify.get("/file", async (req, res) => {
if (!req.query || typeof req.query !== "object" || !("id" in req.query)) return res.code(404).send();
const { id } = req.query;
if (typeof id !== "string") return res.code(401).send();

const file = await getFileLink(id);
if (!file) return res.code(404).send();

return file;
});

fastify.get("/download", async (req, res) => {
if (!req.query || typeof req.query !== "object" || !("id" in req.query)) return res.code(404).send();
const { id } = req.query;
if (typeof id !== "string") return res.code(401).send();

const file = await getFileDownload(id);
if (!file) return res.code(404).send();

return file;
});

done();
};

export const FilesAPI = express.Router();
const upload = multer({
limits: {
fieldNameSize: 1000,
fileSize: 5e6, // 5 MB
files: 50,
},
storage: multer.memoryStorage(),
});

FilesAPI.post("/upload", upload.any(), async (req: Request, res: Response) => {
console.log("Loading files...");
const files = req.files as Express.Multer.File[];
console.log(`Start upload of ${files.length} files...`);
const ret = await uploadFiles(files);

res.status(201).json(ret);
});

FilesAPI.get("/file", async (req: Request, res: Response) => {
if (!req.query || typeof req.query !== "object" || !("id" in req.query)) {
return res.status(404).send();
}

const { id } = req.query;

if (typeof id !== "string") {
return res.status(401).send();
}

const file = await getFileLink(id);
if (!file) {
return res.status(404).send();
}

res.json(file);
});

FilesAPI.get("/download", async (req: Request, res: Response) => {
if (!req.query || typeof req.query !== "object" || !("id" in req.query)) {
return res.status(404).send();
}

const { id } = req.query;

if (typeof id !== "string") {
return res.status(401).send();
}

const file = await getFileDownload(id);
if (!file) {
return res.status(404).send();
}

res.json(file);
});
55 changes: 30 additions & 25 deletions src/routes/pexels.ts
Original file line number Diff line number Diff line change
@@ -1,33 +1,38 @@
import { FastifyPluginCallback } from "fastify";
import express, { Request, Response } from "express";
import { PEXELS_API_KEY } from "../constants";

const RESULTS = "30";
export const PexelsAPI = express.Router();

const RESULTS = 30;
const PEXELS_ENDPOINT = "https://api.pexels.com/v1/search";

export const PexelsAPI: FastifyPluginCallback = async (fastify, _, done) => {
fastify.get("/pexels", async (req, res) => {
if (!req.query || typeof req.query !== "object" || !("query" in req.query)) return res.code(404).send();
const { query } = req.query;
if (typeof query !== "string") return res.code(401).send();
PexelsAPI.get("/pexels", async (req: Request, res: Response) => {
if (!req.query || typeof req.query !== "object" || !("query" in req.query)) {
return res.status(404).send();
}

const params = new URLSearchParams({
query,
per_page: RESULTS,
});
const { query } = req.query;

if (typeof query !== "string") {
return res.status(401).send();
}

try {
const response = await fetch(`${PEXELS_ENDPOINT}?${params}`, {
headers: {
Authorization: PEXELS_API_KEY,
},
});

return await response.json();
} catch (err) {
console.log(`[ERR]: ${err}`);
return { error: true };
}
const params = new URLSearchParams({
query,
per_page: RESULTS.toString(),
});

done();
};
try {
const response = await fetch(`${PEXELS_ENDPOINT}?${params}`, {
headers: {
Authorization: PEXELS_API_KEY,
},
});

const data = await response.json();
res.json(data);
} catch (err) {
console.error(`[ERR]: ${err}`);
res.status(500).json({ error: true });
}
});
9 changes: 5 additions & 4 deletions src/telegram/telegram.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,14 @@ import {
TRIPS_BOT_API_TOKEN,
} from "../constants";
import { throwError } from "../utils/throw";
import { LoadedFile, splitArrayIntoChunks } from "../utils/array";
import { splitArrayIntoChunks } from "../utils/array";

// Disable warning
process.env["NTBA_FIX_350"] = "1";

const bot = new TelegramBot(TRIPS_BOT_API_TOKEN, { filepath: false });

async function uploadFileGroup(files: LoadedFile[], media: InputMediaPhoto[]) {
async function uploadFileGroup(files: Express.Multer.File[], media: InputMediaPhoto[]) {
return (await bot.sendMediaGroup(CHAT_ID, media)).reduce(
(prev, curr, i) => ({
...prev,
Expand All @@ -23,11 +23,11 @@ async function uploadFileGroup(files: LoadedFile[], media: InputMediaPhoto[]) {
);
}

export async function uploadFiles(files: LoadedFile[]) {
export async function uploadFiles(files: Express.Multer.File[]) {
let ret: Record<string, string> = {};
// This library has incorrect typescript typings... InputMediaDocument missing
const media = (await Promise.all(
files.map(async (file) => ({ media: file.content, type: "document" })),
files.map(async (file) => ({ media: file.buffer, type: "document" })),
)) as unknown as InputMediaPhoto[];
const fileChunks = splitArrayIntoChunks(files, TELEGRAM_MAX_PHOTOS_PER_MESSAGE);
const mediaChunks = splitArrayIntoChunks(media, TELEGRAM_MAX_PHOTOS_PER_MESSAGE);
Expand All @@ -44,6 +44,7 @@ export async function uploadFiles(files: LoadedFile[]) {
await new Promise((res) => setTimeout(res, 1000));
}

console.log("Files uploaded successfully");
return ret;
}

Expand Down
14 changes: 0 additions & 14 deletions src/utils/array.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,3 @@
import { MultipartFile } from "@fastify/multipart";

export type LoadedFile = MultipartFile & { content: Buffer };

export function splitArrayIntoChunks<T>(arr: T[], chunkSize: number): T[][] {
const result: T[][] = [];

Expand All @@ -11,13 +7,3 @@ export function splitArrayIntoChunks<T>(arr: T[], chunkSize: number): T[][] {

return result;
}

export async function filesGeneratorToArray(files: AsyncIterableIterator<MultipartFile>) {
const out: LoadedFile[] = [];
let idx = 0;
for await (const file of files) {
console.log(`Loading file #${++idx}...`);
out.push({ ...file, content: await file.toBuffer() });
}
return out;
}

0 comments on commit 6aed3b8

Please sign in to comment.