fix(commands/modlogs): RichEmbed field length

merge-requests/4/head
Hiroyuki 2021-07-26 12:47:07 -04:00
parent a3d15b231c
commit 0bf94819d5
No known key found for this signature in database
GPG Key ID: C15AC26538975A24
7 changed files with 91 additions and 78 deletions

View File

@ -18,6 +18,7 @@
"eris-pagination": "git+https://github.com/bsian03/eris-pagination#c0f77b118e98309e89e6522ef545f9d121601f21", "eris-pagination": "git+https://github.com/bsian03/eris-pagination#c0f77b118e98309e89e6522ef545f9d121601f21",
"express": "^4.17.1", "express": "^4.17.1",
"fs-extra": "^8.1.0", "fs-extra": "^8.1.0",
"hastebin-gen": "^2.0.5",
"helmet": "^3.21.2", "helmet": "^3.21.2",
"ioredis": "^4.14.1", "ioredis": "^4.14.1",
"jsonwebtoken": "^8.5.1", "jsonwebtoken": "^8.5.1",
@ -26,8 +27,7 @@
"mongoose": "^5.7.4", "mongoose": "^5.7.4",
"nodemailer": "^6.3.1", "nodemailer": "^6.3.1",
"signale": "^1.4.0", "signale": "^1.4.0",
"uuid": "^3.3.3", "uuid": "^3.3.3"
"x509": "bsian03/node-x509"
}, },
"devDependencies": { "devDependencies": {
"@types/express": "^4.17.6", "@types/express": "^4.17.6",

View File

@ -1,3 +1,4 @@
/* eslint-disable import/no-unresolved */
/* eslint-disable no-await-in-loop */ /* eslint-disable no-await-in-loop */
/* eslint-disable no-param-reassign */ /* eslint-disable no-param-reassign */
import axios from 'axios'; import axios from 'axios';
@ -8,9 +9,11 @@ import { Message, PrivateChannel, GroupChannel, Member, User } from 'eris';
import uuid from 'uuid/v4'; import uuid from 'uuid/v4';
import moment from 'moment'; import moment from 'moment';
import fs from 'fs'; import fs from 'fs';
import hastebin from 'hastebin-gen';
import { getUserByUid } from '../functions'; import { getUserByUid } from '../functions';
import { AccountUtil, Client, Command, RichEmbed } from '.'; import { AccountUtil, Client, Command, RichEmbed } from '.';
import { ModerationInterface, AccountInterface, Account } from '../models'; import { ModerationInterface, AccountInterface, Account } from '../models';
import { Certificate } from '../../types/x509';
export default class Util { export default class Util {
public client: Client; public client: Client;
@ -310,4 +313,15 @@ export default class Util {
return null; return null;
} }
} }
public parseCertificate(pem: string) {
return axios.post<Certificate>('https://certapi.libraryofcode.org/parse', pem);
}
public upload(text: string, extension = 'txt') {
return hastebin(text, {
url: 'https://snippets.cloud.libraryofcode.org',
extension,
});
}
} }

View File

@ -1,6 +1,5 @@
import fs from 'fs'; import fs from 'fs';
import moment from 'moment'; import moment from 'moment';
import x509 from 'x509';
import { createPaginationEmbed } from 'eris-pagination'; import { createPaginationEmbed } from 'eris-pagination';
import { Message } from 'eris'; import { Message } from 'eris';
import { Client, Command, RichEmbed } from '../class'; import { Client, Command, RichEmbed } from '../class';
@ -30,21 +29,22 @@ export default class CWG_Data extends Command {
} }
return this.error(message.channel, 'The domain or port you provided could not be found.'); return this.error(message.channel, 'The domain or port you provided could not be found.');
} }
const embeds = dom.map((domain) => { const embeds = await Promise.all(dom.map(async (domain) => {
const cert = fs.readFileSync(domain.x509.cert, { encoding: 'utf8' }); const pem = fs.readFileSync(domain.x509.cert, { encoding: 'utf8' });
const cert = await this.client.util.parseCertificate(pem);
const embed = new RichEmbed(); const embed = new RichEmbed();
embed.setTitle('Domain Information'); embed.setTitle('Domain Information');
embed.addField('Account Username', domain.account.username, true); embed.addField('Account Username', domain.account.username, true);
embed.addField('Account ID', domain.account.userID, true); embed.addField('Account ID', domain.account.userID, true);
embed.addField('Domain', domain.domain, true); embed.addField('Domain', domain.domain, true);
embed.addField('Port', String(domain.port), true); embed.addField('Port', String(domain.port), true);
embed.addField('Certificate Issuer', x509.getIssuer(cert).organizationName, true); embed.addField('Certificate Issuer', cert.data.issuer.organization[0], true);
embed.addField('Certificate Subject', x509.getSubject(cert).commonName, true); embed.addField('Certificate Subject', cert.data.issuer.commonName, true);
embed.addField('Certificate Expiration Date', moment(x509.parseCert(cert).notAfter).format('dddd, MMMM Do YYYY, h:mm:ss A'), true); embed.addField('Certificate Expiration Date', moment(cert.data.notAfter).format('dddd, MMMM Do YYYY, h:mm:ss A'), true);
embed.setFooter(this.client.user.username, this.client.user.avatarURL); embed.setFooter(this.client.user.username, this.client.user.avatarURL);
embed.setTimestamp(); embed.setTimestamp();
return embed; return embed;
}); }));
this.client.signale.log(embeds); this.client.signale.log(embeds);
if (embeds.length === 1) return message.channel.createMessage({ embed: embeds[0] }); if (embeds.length === 1) return message.channel.createMessage({ embed: embeds[0] });
return createPaginationEmbed(message, embeds); return createPaginationEmbed(message, embeds);

View File

@ -19,8 +19,8 @@ export default class Modlogs extends Command {
const query = await this.client.db.Moderation.find({ $or: [{ username: args.join(' ') }, { userID: args[0] }] }); const query = await this.client.db.Moderation.find({ $or: [{ username: args.join(' ') }, { userID: args[0] }] });
if (!query.length) return msg.edit(`***${this.client.stores.emojis.error} Cannot locate modlogs for ${args.join(' ')}***`); if (!query.length) return msg.edit(`***${this.client.stores.emojis.error} Cannot locate modlogs for ${args.join(' ')}***`);
const formatted = query.sort((a, b) => a.date.getTime() - b.date.getTime()).map((log) => { const formatted = await Promise.all(query.sort((a, b) => a.date.getTime() - b.date.getTime()).map(async (log) => {
const { username, moderatorID, reason, type, date, logID } = log; const { username, moderatorID, type, date, reason, logID } = log;
let name: string; let name: string;
switch (type) { switch (type) {
default: name = 'Generic'; break; default: name = 'Generic'; break;
@ -30,10 +30,11 @@ export default class Modlogs extends Command {
case 3: name = 'Unlock'; break; case 3: name = 'Unlock'; break;
case 4: name = 'Delete'; break; case 4: name = 'Delete'; break;
} }
const value = `**ID:** ${logID}\n**Account name:** ${username}\n**Moderator:** <@${moderatorID}>\n**Reason:** ${reason || 'Not supplied'}\n**Date:** ${date.toLocaleString('en-us')} EST`; let value = `**ID:** ${logID}\n**Account name:** ${username}\n**Moderator:** <@${moderatorID}>\n**Reason:** ${reason || 'Not supplied'}\n**Date:** ${date.toLocaleString('en-us')} EST`;
if (value.length > 1024) value = value.replace(reason, await this.client.util.upload(reason));
const inline = true; const inline = true;
return { name, value, inline }; return { name, value, inline };
}); }));
const users = [...new Set(query.map((log) => log.userID))].map((u) => `<@${u}>`); const users = [...new Set(query.map((log) => log.userID))].map((u) => `<@${u}>`);
const logs = this.client.util.splitFields(formatted); const logs = this.client.util.splitFields(formatted);

View File

@ -44,7 +44,7 @@
// "baseUrl": "./", /* Base directory to resolve non-absolute module names. */ // "baseUrl": "./", /* Base directory to resolve non-absolute module names. */
// "paths": {}, /* A series of entries which re-map imports to lookup locations relative to the 'baseUrl'. */ // "paths": {}, /* A series of entries which re-map imports to lookup locations relative to the 'baseUrl'. */
// "rootDirs": [], /* List of root folders whose combined content represents the structure of the project at runtime. */ // "rootDirs": [], /* List of root folders whose combined content represents the structure of the project at runtime. */
// "typeRoots": [], /* List of folders to include type definitions from. */ "typeRoots": ["./types"], /* List of folders to include type definitions from. */
// "types": [], /* Type declaration files to be included in compilation. */ // "types": [], /* Type declaration files to be included in compilation. */
// "allowSyntheticDefaultImports": true, /* Allow default imports from modules with no default export. This does not affect code emit, just typechecking. */ // "allowSyntheticDefaultImports": true, /* Allow default imports from modules with no default export. This does not affect code emit, just typechecking. */
"esModuleInterop": true /* Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'. */ "esModuleInterop": true /* Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'. */

97
types/x509.d.ts vendored
View File

@ -1,54 +1,51 @@
declare module 'x509' { export interface Certificate {
namespace Certificate { status: true | false,
interface Issuer { subject: {
countryName: string,
stateOrProvinceName: string,
localityName: string,
organizationName: string,
organizationalUnitName: string,
commonName: string, commonName: string,
emailAddress: string organization: string[],
} organizationalUnit: string[],
interface Subject { locality: string[],
countryName: string, country: string[],
postalCode: string, },
stateOrProvinceName: string, issuer: {
localityName: string,
streetAddress: string,
organizationName: string,
organizationalUnitName: string,
commonName: string, commonName: string,
emailAddress: string organization: string[],
} organizationalUnit: string[],
interface Extensions { locality: string[],
keyUsage: string, country: string[],
authorityInformationAccess: string, },
certificatePolicies: string, aia: {
basicConstraints: string, issuingCertificateURL: string,
cRLDistributionPoints: string, ocspServer: string,
subjectAlternativeName: string, },
extendedKeyUsage: string, validationType: 'DV' | 'OV' | 'EV',
authorityKeyIdentifier: string,
subjectKeyIdentifier: string,
cTPrecertificateSCTs: string
}
}
interface FullCertificate {
version: number,
subject: Certificate.Subject,
issuer: Certificate.Issuer,
fingerPrint: string,
serial: string,
notBefore: Date,
notAfter: Date,
subjectHash: string,
signatureAlgorithm: string, signatureAlgorithm: string,
publicKey: { algorithm: string }; publicKeyAlgorithm: string,
altNames: string[] serialNumber: number,
extensions: Certificate.Extensions notAfter: Date,
} /**
function getAltNames(cert: string): string[]; - 0: KeyUsageCRLSign
function getIssuer(cert: string): Certificate.Issuer; - 1: KeyUsageCertificateSign
function getSubject(cert: string): Certificate.Subject; - 2: KeyUsageContentCommitment
function parseCert(cert: string): FullCertificate - 3: KeyUsageDataEncipherment
- 4: KeyUsageDecipherOnly
- 5: KeyUsageDigitalSignature
- 6: KeyUsageEncipherOnly
- 7: KeyUsageKeyAgreement
- 8: KeyUsageKeyEncipherment
*/
keyUsage: number[],
keyUsageAsText: ['CRL Signing', 'Certificate Signing', 'Content Commitment', 'Data Encipherment', 'Decipher Only', 'Digital Signature', 'Encipher Only', 'Key Agreement', 'Key Encipherment'],
/**
- 0: Any/All Usage
- 1: TLS Web Server Auth
- 2: TLS Web Client Auth
- 3: Code Signing
- 4: Email Protection (S/MIME)
*/
extendedKeyUsage: number[],
extendedKeyUsageAsText: ['All/Any Usages', 'TLS Web Server Authentication', 'TLS Web Client Authentication', 'Code Signing', 'E-mail Protection (S/MIME)'],
san: string,
emailAddresses: string,
fingerprint: string,
} }

View File

@ -1324,6 +1324,13 @@ has@^1.0.3:
dependencies: dependencies:
function-bind "^1.1.1" function-bind "^1.1.1"
hastebin-gen@^2.0.5:
version "2.0.5"
resolved "https://registry.yarnpkg.com/hastebin-gen/-/hastebin-gen-2.0.5.tgz#8f4f11d5c4890280e2dbd34217e6ff06d053fe68"
integrity sha512-At1LaKtcqh2jiP8xfE2sDGT9IshIki6FqsgLwn2y7FzAvlFJRtpUsSPh3yWjWIQIvxi/GPF07IBqSI8WhPL/gQ==
dependencies:
node-fetch "^2.6.0"
helmet-crossdomain@0.4.0: helmet-crossdomain@0.4.0:
version "0.4.0" version "0.4.0"
resolved "https://registry.yarnpkg.com/helmet-crossdomain/-/helmet-crossdomain-0.4.0.tgz#5f1fe5a836d0325f1da0a78eaa5fd8429078894e" resolved "https://registry.yarnpkg.com/helmet-crossdomain/-/helmet-crossdomain-0.4.0.tgz#5f1fe5a836d0325f1da0a78eaa5fd8429078894e"
@ -1965,11 +1972,6 @@ mute-stream@0.0.8:
resolved "https://registry.yarnpkg.com/mute-stream/-/mute-stream-0.0.8.tgz#1630c42b2251ff81e2a283de96a5497ea92e5e0d" resolved "https://registry.yarnpkg.com/mute-stream/-/mute-stream-0.0.8.tgz#1630c42b2251ff81e2a283de96a5497ea92e5e0d"
integrity sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA== integrity sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA==
nan@2.14.1:
version "2.14.1"
resolved "https://registry.yarnpkg.com/nan/-/nan-2.14.1.tgz#d7be34dfa3105b91494c3147089315eff8874b01"
integrity sha512-isWHgVjnFjh2x2yuJ/tj3JbwoHu3UC2dX5G/88Cm24yB6YopVgxvBObDY7n5xW6ExmFhJpSEQqFPvq9zaXc8Jw==
natural-compare@^1.4.0: natural-compare@^1.4.0:
version "1.4.0" version "1.4.0"
resolved "https://registry.yarnpkg.com/natural-compare/-/natural-compare-1.4.0.tgz#4abebfeed7541f2c27acfb29bdbbd15c8d5ba4f7" resolved "https://registry.yarnpkg.com/natural-compare/-/natural-compare-1.4.0.tgz#4abebfeed7541f2c27acfb29bdbbd15c8d5ba4f7"
@ -1990,6 +1992,11 @@ nocache@2.1.0:
resolved "https://registry.yarnpkg.com/nocache/-/nocache-2.1.0.tgz#120c9ffec43b5729b1d5de88cd71aa75a0ba491f" resolved "https://registry.yarnpkg.com/nocache/-/nocache-2.1.0.tgz#120c9ffec43b5729b1d5de88cd71aa75a0ba491f"
integrity sha512-0L9FvHG3nfnnmaEQPjT9xhfN4ISk0A8/2j4M37Np4mcDesJjHgEUfgPhdCyZuFI954tjokaIj/A3NdpFNdEh4Q== integrity sha512-0L9FvHG3nfnnmaEQPjT9xhfN4ISk0A8/2j4M37Np4mcDesJjHgEUfgPhdCyZuFI954tjokaIj/A3NdpFNdEh4Q==
node-fetch@^2.6.0:
version "2.6.1"
resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.1.tgz#045bd323631f76ed2e2b55573394416b639a0052"
integrity sha512-V4aYg89jEoVRxRb2fJdAg8FHvI7cEyYdVAh94HH0UIK8oJxUfkjlDQN9RbMx+bEjP7+ggMiFRprSti032Oipxw==
node-source-walk@^4.0.0, node-source-walk@^4.2.0: node-source-walk@^4.0.0, node-source-walk@^4.2.0:
version "4.2.0" version "4.2.0"
resolved "https://registry.yarnpkg.com/node-source-walk/-/node-source-walk-4.2.0.tgz#c2efe731ea8ba9c03c562aa0a9d984e54f27bc2c" resolved "https://registry.yarnpkg.com/node-source-walk/-/node-source-walk-4.2.0.tgz#c2efe731ea8ba9c03c562aa0a9d984e54f27bc2c"
@ -2978,9 +2985,3 @@ x-xss-protection@1.3.0:
version "1.3.0" version "1.3.0"
resolved "https://registry.yarnpkg.com/x-xss-protection/-/x-xss-protection-1.3.0.tgz#3e3a8dd638da80421b0e9fff11a2dbe168f6d52c" resolved "https://registry.yarnpkg.com/x-xss-protection/-/x-xss-protection-1.3.0.tgz#3e3a8dd638da80421b0e9fff11a2dbe168f6d52c"
integrity sha512-kpyBI9TlVipZO4diReZMAHWtS0MMa/7Kgx8hwG/EuZLiA6sg4Ah/4TRdASHhRRN3boobzcYgFRUFSgHRge6Qhg== integrity sha512-kpyBI9TlVipZO4diReZMAHWtS0MMa/7Kgx8hwG/EuZLiA6sg4Ah/4TRdASHhRRN3boobzcYgFRUFSgHRge6Qhg==
x509@bsian03/node-x509:
version "0.3.4"
resolved "https://codeload.github.com/bsian03/node-x509/tar.gz/cc32d7f590ec43cb856effbb4202921f3fa9aef3"
dependencies:
nan "2.14.1"