Skip to content

Commit

Permalink
chore: make encryption better & use asyncrhonous fs
Browse files Browse the repository at this point in the history
  • Loading branch information
dev-737 committed Jun 17, 2024
1 parent 5a7ac0f commit b0909eb
Show file tree
Hide file tree
Showing 10 changed files with 102 additions and 161 deletions.
4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@
"winston": "^3.13.0"
},
"devDependencies": {
"@stylistic/eslint-plugin": "^2.1.0",
"@stylistic/eslint-plugin": "^2.2.1",
"@types/common-tags": "^1.8.4",
"@types/express": "^4.17.21",
"@types/js-yaml": "^4.0.9",
Expand All @@ -49,7 +49,7 @@
"@types/source-map-support": "^0.5.10",
"cz-conventional-changelog": "^3.3.0",
"eslint": "8.57.0",
"lint-staged": "^15.2.6",
"lint-staged": "^15.2.7",
"prettier": "^3.3.2",
"prisma": "^5.15.0",
"standard-version": "^9.5.0",
Expand Down
2 changes: 1 addition & 1 deletion src/core/Client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,7 @@ export default class SuperClient extends Client {
SuperClient.instance = this;

// initialize i18n for localization
loadLocales('locales/src/locales');
await loadLocales('locales/src/locales');

// load commands
await loadCommandFiles();
Expand Down
6 changes: 6 additions & 0 deletions src/scripts/network/helpers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import {
ButtonStyle,
ButtonBuilder,
ActionRowBuilder,
APIMessage,
} from 'discord.js';
import db from '../../utils/Db.js';
import { LINKS, REGEX, emojis } from '../../utils/Constants.js';
Expand Down Expand Up @@ -172,3 +173,8 @@ export const sendWelcomeMsg = async (message: Message, totalServers: string, hub
})
.catch(() => null);
};


export function isNetworkApiError(res: string | APIMessage | undefined): res is string {
return (res && typeof res === 'string') === true;
}
39 changes: 21 additions & 18 deletions src/scripts/network/sendMessage.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { APIEmbed, APIMessage, WebhookMessageCreateOptions } from 'discord.js';
import { APIEmbed, APIMessage, WebhookMessageCreateOptions, isJSONEncodable } from 'discord.js';
// import { isDevBuild } from '../../utils/Constants.js';
import { encryptMessage } from '../../utils/Utils.js';
import { isNetworkApiError } from './helpers.js';

const { INTERCHAT_API_URL1, INTERCHAT_API_URL2 } = process.env;
let primaryUrl = INTERCHAT_API_URL1 ?? INTERCHAT_API_URL2;
Expand Down Expand Up @@ -29,37 +30,39 @@ const sendMessage = async (
throw new Error('NETWORK_API_KEY or INTERCHAT_API_URL(s) env variables missing.');
}

const embed = message.embeds?.at(0) as APIEmbed;
const firstEmbed = message.embeds?.at(0);
const embed = isJSONEncodable(firstEmbed) ? firstEmbed.toJSON() : firstEmbed;

const content = message.content;
if (encrypt && content) message.content = encryptMessage(content, encryptKey);
if (encrypt && embed.description) {
(message.embeds as APIEmbed[])![0].description = encryptMessage(embed.description, encryptKey);
if (encrypt) {
if (content) message.content = encryptMessage(content, encryptKey);
if (embed?.description) {
// FIXME: message.embeds[0] might not work if its json encodable, check!
(message.embeds as APIEmbed[])![0].description = encryptMessage(
embed.description,
encryptKey,
);
}
}

console.log(primaryUrl);

const res = await fetch(primaryUrl, {
method: 'PUT',
method: 'POST',
body: JSON.stringify({ webhookUrl, data: message }),
headers: {
authorization: networkKey,
'x-webhook-url': webhookUrl,
'Content-Type': 'application/json',
},
});
console.log(res);

const data = await res.json();
console.log(data);
if (res.status !== 200) {
if (tries <= 2) {
primaryUrl = switchUrl(primaryUrl);
return await sendMessage(webhookUrl, message, tries++, !encrypt);
}
return String(data.error);
const data = (await res.json()) as string | APIMessage | undefined;

if (isNetworkApiError(data) && tries <= 2) {
primaryUrl = switchUrl(primaryUrl);
return await sendMessage(webhookUrl, message, tries++, !encrypt);
}

return data.result as APIMessage;
return data;
};

export default sendMessage;
36 changes: 19 additions & 17 deletions src/scripts/network/storeMessageData.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import db from '../../utils/Db.js';
import { originalMessages } from '@prisma/client';
import { APIMessage, Message } from 'discord.js';
import { messageTimestamps, modifyConnections } from '../../utils/ConnectedList.js';
import { handleError, parseTimestampFromId } from '../../utils/Utils.js';
import { isNetworkApiError } from './helpers.js';

export interface NetworkWebhookSendResult {
messageOrError: APIMessage | string;
Expand All @@ -20,20 +20,21 @@ export default async (
hubId: string,
dbReference?: originalMessages | null,
) => {
const messageDataObj: { channelId: string; messageId: string, createdAt: Date }[] = [];
const messageDataObj: { channelId: string; messageId: string; createdAt: Date }[] = [];
const invalidWebhookURLs: string[] = [];
const validErrors = ['Invalid Webhook Token', 'Unknown Webhook', 'Missing Permissions'];

// loop through all results and extract message data and invalid webhook urls
channelAndMessageIds.forEach(({ messageOrError, webhookURL }) => {
if (messageOrError && typeof messageOrError !== 'string') {
if (!isNetworkApiError(messageOrError)) {
messageDataObj.push({
channelId: messageOrError.channel_id,
messageId: messageOrError.id,
createdAt: new Date(parseTimestampFromId(messageOrError.id)),
createdAt: new Date(messageOrError.timestamp),
});
}
else if (validErrors.some((e) => (messageOrError as string).includes(e))) {
else if (validErrors.some((e) => messageOrError?.includes(e))) {
console.log(messageOrError);
invalidWebhookURLs.push(webhookURL);
}
});
Expand All @@ -42,18 +43,19 @@ export default async (
if (!message.inGuild()) return;

// store message data in db
await db.originalMessages.create({
data: {
messageId: message.id,
authorId: message.author.id,
serverId: message.guildId,
messageReference: dbReference?.messageId,
createdAt: message.createdAt,
broadcastMsgs: { createMany: { data: messageDataObj } },
hub: { connect: { id: hubId } },
reactions: {},
},
}).catch(handleError);
await db.originalMessages
.create({
data: {
messageId: message.id,
authorId: message.author.id,
serverId: message.guildId,
messageReference: dbReference?.messageId,
createdAt: message.createdAt,
broadcastMsgs: { createMany: { data: messageDataObj } },
hub: { connect: { id: hubId } },
reactions: {},
},
});
}

// store message timestamps to push to db later
Expand Down
3 changes: 1 addition & 2 deletions src/utils/ConnectedList.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ import db from './Db.js';
import Logger from './Logger.js';
import { Prisma, connectedList } from '@prisma/client';
import { Collection } from 'discord.js';
import { handleError } from './Utils.js';
import { captureException } from '@sentry/node';

/** 📡 Contains all the **connected** channels from all hubs. */
Expand Down Expand Up @@ -72,6 +71,6 @@ export const modifyConnections = async (
export const storeMsgTimestamps = (data: Collection<string, Date>): void => {
data.forEach(
async (lastActive, channelId) =>
await modifyConnection({ channelId }, { lastActive }).catch(handleError),
await modifyConnection({ channelId }, { lastActive }),
);
};
12 changes: 6 additions & 6 deletions src/utils/LoadCommands.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { join, dirname } from 'path';
import { access, constants, readdirSync, statSync } from 'fs';
import { access, constants, readdir, stat } from 'fs/promises';
import { fileURLToPath } from 'url';
import BaseCommand, { commandsMap } from '../core/BaseCommand.js';

Expand All @@ -11,17 +11,17 @@ const __dirname = dirname(fileURLToPath(import.meta.url));
*/
const loadCommandFiles = async (commandDir = join(__dirname, '..', 'commands')) => {
const importPrefix = process.platform === 'win32' ? 'file://' : '';
const files = readdirSync(commandDir);
const files = await readdir(commandDir);

for (const file of files) {
const filePath = join(commandDir, file);
const stats = statSync(filePath);
const stats = await stat(filePath);

// If the item is a directory, recursively read its files
if (stats.isDirectory()) {
await loadCommandFiles(filePath);
}
else if (file.endsWith('.js') && file !== 'BaseCommand.js') {
else if (file.endsWith('.js')) {
const imported = await import(importPrefix + filePath);
const command: BaseCommand = new imported.default();

Expand All @@ -33,9 +33,9 @@ const loadCommandFiles = async (commandDir = join(__dirname, '..', 'commands'))
// if the command has subcommands, add them to the parent command's subcommands map
else {
const subcommandFile = join(commandDir, '.', 'index.js');
if (!statSync(subcommandFile).isFile()) return;
if (!(await stat(subcommandFile)).isFile()) return;

access(subcommandFile, constants.F_OK, (err) => {
await access(subcommandFile, constants.F_OK).catch((err) => {
if (err || file === 'index.js') return;

// get the parent command class from the subcommand
Expand Down
14 changes: 7 additions & 7 deletions src/utils/Locale.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import Logger from './Logger.js';
import fs from 'fs';
import fs from 'fs/promises';
import path from 'path';
import yaml from 'js-yaml';

Expand Down Expand Up @@ -41,20 +41,20 @@ export interface tParams {
locale?: supportedLocaleCodes;
}

export const loadLocales = (localesDirectory: string) => {
const files = fs.readdirSync(localesDirectory);
export const loadLocales = async (localesDirectory: string) => {
const files = await fs.readdir(localesDirectory);

files.forEach((file: string) => {
files.forEach(async (file: string, index) => {
const filePath = path.join(localesDirectory, file);
const localeKey = path.basename(file, '.yml');

const content = fs.readFileSync(filePath, 'utf8');
const content = await fs.readFile(filePath, 'utf8');
const parsedContent = yaml.load(content);

localesMap.set(localeKey, parsedContent);
});

Logger.info(`${localesMap.size} Locales loaded successfully.`);
if (index + 1 === files.length) Logger.info(`${localesMap.size} Locales loaded successfully.`);
});
};

/** Get the translated text with variable replacement */
Expand Down
5 changes: 3 additions & 2 deletions src/utils/Logger.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,15 @@
import { createLogger, format, transports } from 'winston';
import 'source-map-support/register.js';

const custom = format.printf(
(info) =>
`${info.level}: ${info.message} | ${info.timestamp} ${info.stack ? `\n${info.stack}` : ''}`,
`${info.timestamp} ${info.level}: ${info.message} ${info.stack ? `\n${info.stack}` : ''}`,
);

const combinedFormat = format.combine(
format.errors({ stack: true }),
format.splat(),
format.timestamp({ format: '[on] DD MMMM, YYYY [at] hh:mm:ss.SSS' }),
format.timestamp({ format: 'DD/MM/YY-HH:mm:ss' }),
format((info) => {
info.level = info.level.toUpperCase();
return info;
Expand Down
Loading

0 comments on commit b0909eb

Please sign in to comment.