jillo-bot/src/lib/util.ts

132 lines
3.5 KiB
TypeScript

import * as fsp from 'fs/promises';
import { tmpdir } from 'os';
import { join } from 'path';
import { randomBytes } from 'crypto';
import { Attachment, EmbedBuilder, Guild, GuildPremiumTier, Message, PartialMessage } from 'discord.js';
export async function exists(file: string) {
try {
await fsp.stat(file);
return true;
} catch(_err) {
return false;
}
}
export function getSign(n: number) {
if (n > 0) return '+';
if (n < 0) return '-';
return ' ';
}
export async function writeTmpFile(data: string | Buffer, filename?: string, extension?: string): Promise<string> {
const file = `${filename ? filename + '-' : ''}${randomBytes(8).toString('hex')}${extension ? '.' + extension : (typeof data === 'string' ? '.txt' : '')}`;
const path = join(tmpdir(), file);
await fsp.writeFile(path, data);
return path;
}
export function pickRandom<T>(list: T[]): T {
return list[Math.floor(Math.random() * list.length)];
}
// WE OUT HERE
export type Either<L,R> = Left<L> | Right<R>
export class Left<L> {
constructor(private readonly value: L) {}
public getValue() { return this.value; }
}
export class Right<R> {
constructor(private readonly value: R) {}
public getValue() { return this.value; }
}
export function* chunks<T>(arr: T[], n: number) {
for (let i = 0; i < arr.length; i += n) {
yield arr.slice(i, i + n);
}
}
export function shortenStr(str: string, chars: number) {
if (str.length > chars)
return str.slice(0, chars - 1) + '…';
return str;
}
export const MAX_MESSAGE_SIZE = 2000;
export const defaultUploadLimit = 25 * 1024 * 1024;
export const getUploadLimitForGuild = (guild: Guild) => {
switch (guild.premiumTier) {
case GuildPremiumTier.Tier3: return 100 * 1024 * 1024;
case GuildPremiumTier.Tier2: return 50 * 1024 * 1024;
default: return defaultUploadLimit;
}
};
export function formatMessageAsEmbed(message: Message | PartialMessage, uploadLimit: number): { embed: EmbedBuilder, attach: Attachment | null } {
const embed = new EmbedBuilder()
.setTimestamp(message.createdTimestamp);
if (message.author) {
embed.setAuthor({
name: message.author.tag,
iconURL: message.author.displayAvatarURL(),
});
}
let attach = null;
message.embeds.forEach(em => {
if (em.image) {
embed.setImage(em.image.url);
} else if (em.thumbnail) {
embed.setImage(em.thumbnail.url);
}
if (em.provider) {
embed.addFields({
name: shortenStr(`${em.provider.name}:`, 256),
value: shortenStr(`${em.author}: **${em.title}**\n${em.description || ''}`, 2048),
});
} else if (!em.image) {
embed.addFields({
name: 'Embed:',
value: shortenStr(em.description || em.fields[0]?.value || em.title || 'Unknown content', 2048),
});
}
});
let msgEnd = null;
const first = message.attachments.first();
if (
message.attachments.size === 1 && first && first.contentType
&& !first.spoiler
&& (first.contentType?.startsWith('image/')
|| first.contentType?.startsWith('video/'))
&& (first.size <= uploadLimit)
) {
attach = first;
} else {
for (const attach of message.attachments.values()) {
msgEnd = (msgEnd || '\n') + `\n[${attach.name}](${attach.url})`;
}
}
if (message.content) {
if (!msgEnd) {
embed.setDescription(shortenStr(message.content, 4096));
} else {
embed.setDescription(shortenStr(message.content, 4096 - msgEnd.length) + msgEnd);
}
} else if (msgEnd) {
embed.setDescription('_Content unknown_' + msgEnd);
}
return { embed, attach };
}