for coded
diff --git a/src/utils/calculate.ts b/src/utils/calculate.ts
new file mode 100644
index 0000000..174c401
--- /dev/null
+++ b/src/utils/calculate.ts
@@ -0,0 +1,66 @@
+const logs = [
+ "channelUpdate",
+ "channelPinsUpdate",
+ "emojiUpdate",
+ "stickerUpdate",
+ "guildUpdate",
+ "guildMemberUpdate",
+ "guildMemberPunish",
+ "guildEventUpdate",
+ "guildEventMemberUpdate",
+ "guildRoleUpdate",
+ "guildInviteUpdate",
+ "messageUpdate",
+ "messageDelete",
+ "messageDeleteBulk",
+ "messageReactionUpdate",
+ "messagePing",
+ "messageMassPing",
+ "messageAnnounce",
+ "stageUpdate",
+ "threadUpdate",
+ "voiceStateUpdate",
+ "webhookUpdate"
+]
+
+const tickets = [
+ "support",
+ "report",
+ "question",
+ "issue",
+ "suggestion",
+ "other"
+]
+
+const toHexInteger = (permissions, array?) => {
+ if (!array) {
+ array = logs;
+ }
+ let int = 0n;
+
+ for(let perm of permissions) {
+ int += BigInt(2 ** array.indexOf(perm));
+ }
+ return int.toString(16)
+}
+
+const toHexArray = (permissionsHex, array?) => {
+ if (!array) {
+ array = logs;
+ }
+ let permissions = [];
+ let int = (BigInt("0x" + permissionsHex)).toString(2).split('').reverse();
+ for (let index in int) {
+ if (int[index] == "1") {
+ permissions.push(array[index]);
+ }
+ }
+ return permissions;
+}
+
+export {
+ toHexInteger,
+ toHexArray,
+ tickets,
+ logs
+}
\ No newline at end of file
diff --git a/src/utils/convertCurlyBracketString.ts b/src/utils/convertCurlyBracketString.ts
new file mode 100644
index 0000000..093e522
--- /dev/null
+++ b/src/utils/convertCurlyBracketString.ts
@@ -0,0 +1,15 @@
+async function convertCurlyBracketString(str, memberID, memberName, serverName, members): Promise<string> {
+ let memberCount = (await members.fetch()).size
+ let bots = (await members.fetch()).filter(m => m.user.bot).size
+ str = str
+ .replace("{@}", `<@${memberID}>`)
+ .replace("{server}", `${serverName}`)
+ .replace("{name}", `${memberName}`)
+ .replace("{count}", `${memberCount}`)
+ .replace("{count:bots}", `${bots}`)
+ .replace("{count:humans}", `${memberCount - bots}`);
+
+ return str
+}
+
+export default convertCurlyBracketString;
\ No newline at end of file
diff --git a/src/utils/generateConfig.ts b/src/utils/generateConfig.ts
new file mode 100644
index 0000000..6dc4e52
--- /dev/null
+++ b/src/utils/generateConfig.ts
@@ -0,0 +1,92 @@
+import * as fs from 'fs';
+
+function writeLogConfig(guild, logs) {
+ if( !fs.existsSync(`./data/guilds/${guild.id}/config.json`) ) {
+ fs.rmSync(`./data/guilds/${guild.id}/config.json`);
+ }
+ if( !fs.existsSync(`./data/guilds/${guild.id}/pins.json`) ) {
+ let pins = guild.channels.cache.filter(c => c.type === "GUILD_TEXT").map(
+ c => c.messages.fetchPinned().then(m => m.map(m => m.id))
+ );
+ fs.writeFileSync(`./data/guilds/${guild.id}/pins.json`, JSON.stringify(pins));
+ }
+ if( !fs.existsSync(`./data/guilds/${guild.id}/logs.json`) ) {
+ fs.writeFileSync(`./data/guilds/${guild.id}/logs.json`, JSON.stringify([]));
+ } else if( logs ) {
+ fs.rmSync(`./data/guilds/${guild.id}/logs.json`);
+ fs.writeFileSync(`./data/guilds/${guild.id}/logs.json`, JSON.stringify([]));
+ }
+ fs.writeFileSync(`./data/guilds/${guild.id}/config.json`, JSON.stringify({
+ metadata: {
+ premium: false
+ },
+ logs: {
+ enabled: true,
+ logChannel: guild.systemChannelId,
+ toLog: "8be71",
+ toIgnore: {
+ bots: false,
+ channels: [],
+ members: [],
+ roles: []
+ }
+ },
+ userVerification: {
+ enabled: false,
+ roleID: null,
+ customMessage: null
+ },
+ modmail: {
+ enabled: false,
+ categoryId: null,
+ namingScheme: "rsm-{user}-{discriminator}",
+ },
+ welcome: {
+ enabled: false,
+ channelId: null,
+ message: null,
+ messageType: "embed",
+ },
+ filters: {
+ images: {
+ NSFW: true,
+ size: true
+ },
+ malware: true,
+ wordFilter: {
+ enabled: true,
+ words: {
+ strict: [],
+ loose: []
+ },
+ allowed: {
+ users: [],
+ roles: [],
+ channels: []
+ }
+ },
+ invite: {
+ enabled: true,
+ allowed: {
+ users: [],
+ channels: [],
+ roles: []
+ }
+ },
+ pings: {
+ mass: 5,
+ everyone: true,
+ roles: true,
+ allowed: {
+ roles: [],
+ rolesToMention: [],
+ users: [],
+ channels: []
+ }
+ }
+ },
+ tags: {}
+ }));
+}
+
+export default writeLogConfig;
\ No newline at end of file
diff --git a/src/utils/log.ts b/src/utils/log.ts
new file mode 100644
index 0000000..d807831
--- /dev/null
+++ b/src/utils/log.ts
@@ -0,0 +1,101 @@
+import * as fs from 'fs';
+import * as Discord from 'discord.js';
+import getEmojiByName from './getEmojiByName.js';
+import readConfig from './readConfig.js';
+import { toHexArray } from './calculate.js';
+import { promisify } from 'util';
+import generateKeyValueList from './generateKeyValueList.js';
+
+const wait = promisify(setTimeout);
+
+
+export class Logger {
+ renderUser(user: Discord.User) {
+ return `${user.username} [<@${user.id}>]`;
+ }
+ renderTime(t: number) {
+ t = Math.floor(t /= 1000)
+ return `<t:${t}:D> at <t:${t}:T>`;
+ }
+ renderDelta(t: number) {
+ t = Math.floor(t /= 1000)
+ return `<t:${t}:R> (<t:${t}:D> at <t:${t}:T>)`;
+ }
+ renderNumberDelta(num1, num2) {
+ let delta = num2 - num1;
+ return `${num1} -> ${num2} (${delta > 0 ? '+' : ''}${delta})`;
+ }
+ entry(value, displayValue) {
+ return { value: value, displayValue: displayValue }
+ }
+ renderChannel(channel: Discord.GuildChannel) {
+ return `${channel.name} [<#${channel.id}>]`;
+ }
+ renderRole(role: Discord.Role) {
+ return `${role.name} [<@&${role.id}>]`;
+ }
+ renderEmoji(emoji: Discord.GuildEmoji) {
+ return `<${emoji.animated ? 'a' : ''}:${emoji.name}:${emoji.id}> [\`:${emoji.name}:\`]`;
+ }
+
+ public readonly NucleusColors = {
+ red: 0xF27878,
+ yellow: 0xF2D478,
+ green: 0x68D49E,
+
+ }
+
+
+ async getAuditLog(guild: Discord.Guild, event) {
+ await wait(250)
+ let auditLog = await guild.fetchAuditLogs({type: event});
+ return auditLog;
+ }
+
+ async log(log: any, client): Promise<void> {
+ let config = await readConfig(log.hidden.guild);
+ if (!config.logging.logs.enabled) return;
+ if (!(log.meta.calculateType == true)) if(!toHexArray(config.logging.logs.toLog).includes(log.meta.calculateType)) return console.log('Not logging this type of event');
+ if (config.logging.logs.channel) {
+ let channel = await client.channels.fetch(config.logging.logs.channel) as Discord.TextChannel;
+ let description = {};
+ Object.entries(log.list).map(entry => {
+ let key = entry[0];
+ let value:any = entry[1];
+ if(value.displayValue) {
+ description[key] = value.displayValue;
+ } else {
+ description[key] = value;
+ }
+ })
+ if (channel) {
+ log.separate = log.separate || {};
+ let embed = new Discord.MessageEmbed()
+ .setTitle(`${getEmojiByName(log.meta.emoji)} ${log.meta.displayName}`)
+ .setDescription(
+ (log.separate.start ? log.separate.start + "\n" : "") +
+ generateKeyValueList(description) +
+ (log.separate.end ? "\n" + log.separate.end : "")
+ )
+ .setTimestamp(log.meta.timestamp)
+ .setColor(log.meta.color);
+ channel.send({embeds: [embed]});
+ }
+ }
+ saveLog(log);
+ }
+}
+
+
+export default {}
+
+async function saveLog(log: any): Promise<void> {
+}
+
+export function readLogs(guild: string) {
+
+}
+
+export function readSpecificLog(guild: string, id: number) {
+
+}
diff --git a/src/utils/readConfig.ts b/src/utils/readConfig.ts
new file mode 100644
index 0000000..c53d2cc
--- /dev/null
+++ b/src/utils/readConfig.ts
@@ -0,0 +1,85 @@
+
+export default async function readConfig(guild: string): Promise<any> {
+
+ let config = {
+ filters: {
+ images: {
+ NSFW: true,
+ size: true
+ },
+ malware: true,
+ wordFilter: {
+ enabled: true,
+ words: {
+ strict: [],
+ loose: []
+ },
+ allowed: {
+ users: [],
+ roles: [],
+ channels: []
+ }
+ },
+ invite: {
+ enabled: false,
+ allowed: {
+ users: [],
+ channels: [],
+ roles: []
+ }
+ },
+ pings: {
+ mass: 5,
+ everyone: true,
+ roles: true,
+ allowed: {
+ roles: [],
+ rolesToMention: [],
+ users: [],
+ channels: []
+ }
+ }
+ },
+ welcome: {
+ enabled: true,
+ verificationRequired: {
+ message: false,
+ role: false
+ },
+ welcomeRole: null,
+ channel: '895209752315961344', // null, channel ID or 'dm'
+ message: "Welcome to the server, {@}!"
+ },
+ stats: [
+ {
+ enabled: true,
+ channel: '951910554291818526',
+ text: "{count} members | {count:bots} bots | {count:humans} humans"
+ }
+ ],
+ logging: {
+ logs: {
+ enabled: true,
+ channel: '952247098437427260',
+ toLog: "3fffff" // "3ffffe" = - channelUpdate, "3fffff" = all
+ },
+ staff: {}
+ },
+ verify: {
+ enabled: true,
+ channel: '895210691479355392',
+ role: '934941369137524816',
+ },
+ tickets: {
+ enabled: true,
+ category: "952302254302584932",
+ types: "3f",
+ customTypes: null,
+ supportRole: null,
+ maxTickets: 5
+ }
+ };
+
+ return config
+
+}
\ No newline at end of file
diff --git a/src/utils/scanners.ts b/src/utils/scanners.ts
new file mode 100644
index 0000000..97e9bf4
--- /dev/null
+++ b/src/utils/scanners.ts
@@ -0,0 +1,30 @@
+import * as us from 'unscan'
+import fetch from 'node-fetch'
+import { writeFileSync } from 'fs'
+import generateFileName from './temp/generateFileName.js'
+import * as path from 'path'
+import {fileURLToPath} from 'url';
+const __filename = fileURLToPath(import.meta.url);
+const __dirname = path.dirname(__filename);
+
+export async function testNSFW(link: string): Promise<JSON> {
+ const image = (await (await fetch(link)).buffer()).toString('base64')
+ let fileName = generateFileName(link.split('/').pop().split('.').pop())
+ let p = path.join(__dirname, '/temp', fileName)
+ writeFileSync(p, image, 'base64')
+ let result = await us.nsfw.file(p)
+ return result
+}
+
+export async function testMalware(link: string): Promise<JSON> {
+ const file = (await (await fetch(link)).buffer()).toString('base64')
+ let fileName = generateFileName(link.split('/').pop().split('.').pop())
+ let p = path.join(__dirname, '/temp', fileName)
+ writeFileSync(p, file, 'base64')
+ let result = await us.malware.file(p)
+ return result
+}
+
+export async function testLink(link: string): Promise<JSON> {
+ return await us.link.scan(link)
+}
diff --git a/src/utils/temp/generateFileName.ts b/src/utils/temp/generateFileName.ts
new file mode 100644
index 0000000..98240a1
--- /dev/null
+++ b/src/utils/temp/generateFileName.ts
@@ -0,0 +1,11 @@
+import * as fs from 'fs';
+import * as crypto from 'crypto';
+
+export default function generateFileName(ending: string): string {
+ let fileName = crypto.randomBytes(35).toString('hex');
+ fileName = fileName.replace(/([a-zA-Z0-9]{8})/g, '$1-');
+ if (fs.existsSync(`./${fileName}`)) {
+ fileName = generateFileName(ending);
+ }
+ return fileName + '.' + ending;
+}
\ No newline at end of file