mirror of
https://github.com/ZeppelinBot/Zeppelin.git
synced 2025-03-16 22:21:51 +00:00
tags: add support for embeds
This commit is contained in:
parent
7f02aec20c
commit
1cff4fb801
2 changed files with 66 additions and 12 deletions
|
@ -1,6 +1,14 @@
|
||||||
import { decorators as d, IPluginOptions, logger } from "knub";
|
import { decorators as d, IPluginOptions, logger } from "knub";
|
||||||
import { Member, Message, TextChannel } from "eris";
|
import { Member, Message, TextChannel } from "eris";
|
||||||
import { errorMessage, successMessage, stripObjectToScalars, tNullable, convertDelayStringToMS } from "../utils";
|
import {
|
||||||
|
convertDelayStringToMS,
|
||||||
|
errorMessage,
|
||||||
|
StrictMessageContent,
|
||||||
|
stripObjectToScalars,
|
||||||
|
tEmbed,
|
||||||
|
tNullable,
|
||||||
|
tStrictMessageContent,
|
||||||
|
} from "../utils";
|
||||||
import { GuildTags } from "../data/GuildTags";
|
import { GuildTags } from "../data/GuildTags";
|
||||||
import { GuildSavedMessages } from "../data/GuildSavedMessages";
|
import { GuildSavedMessages } from "../data/GuildSavedMessages";
|
||||||
import { SavedMessage } from "../data/entities/SavedMessage";
|
import { SavedMessage } from "../data/entities/SavedMessage";
|
||||||
|
@ -12,6 +20,11 @@ import { GuildArchives } from "../data/GuildArchives";
|
||||||
import * as t from "io-ts";
|
import * as t from "io-ts";
|
||||||
import { parseArguments } from "knub-command-manager";
|
import { parseArguments } from "knub-command-manager";
|
||||||
import escapeStringRegexp from "escape-string-regexp";
|
import escapeStringRegexp from "escape-string-regexp";
|
||||||
|
import { validate } from "../validatorUtils";
|
||||||
|
import { GuildLogs } from "../data/GuildLogs";
|
||||||
|
import { LogType } from "../data/LogType";
|
||||||
|
|
||||||
|
const Tag = t.union([t.string, tEmbed]);
|
||||||
|
|
||||||
const TagCategory = t.type({
|
const TagCategory = t.type({
|
||||||
prefix: tNullable(t.string),
|
prefix: tNullable(t.string),
|
||||||
|
@ -22,7 +35,7 @@ const TagCategory = t.type({
|
||||||
global_tag_cooldown: tNullable(t.union([t.string, t.number])), // Any user, per tag
|
global_tag_cooldown: tNullable(t.union([t.string, t.number])), // Any user, per tag
|
||||||
global_category_cooldown: tNullable(t.union([t.string, t.number])), // Any user, per category
|
global_category_cooldown: tNullable(t.union([t.string, t.number])), // Any user, per category
|
||||||
|
|
||||||
tags: t.record(t.string, t.string),
|
tags: t.record(t.string, Tag),
|
||||||
|
|
||||||
can_use: tNullable(t.boolean),
|
can_use: tNullable(t.boolean),
|
||||||
});
|
});
|
||||||
|
@ -55,6 +68,7 @@ export class TagsPlugin extends ZeppelinPlugin<TConfigSchema> {
|
||||||
protected archives: GuildArchives;
|
protected archives: GuildArchives;
|
||||||
protected tags: GuildTags;
|
protected tags: GuildTags;
|
||||||
protected savedMessages: GuildSavedMessages;
|
protected savedMessages: GuildSavedMessages;
|
||||||
|
protected logs: GuildLogs;
|
||||||
|
|
||||||
private onMessageCreateFn;
|
private onMessageCreateFn;
|
||||||
private onMessageDeleteFn;
|
private onMessageDeleteFn;
|
||||||
|
@ -96,6 +110,7 @@ export class TagsPlugin extends ZeppelinPlugin<TConfigSchema> {
|
||||||
this.archives = GuildArchives.getGuildInstance(this.guildId);
|
this.archives = GuildArchives.getGuildInstance(this.guildId);
|
||||||
this.tags = GuildTags.getGuildInstance(this.guildId);
|
this.tags = GuildTags.getGuildInstance(this.guildId);
|
||||||
this.savedMessages = GuildSavedMessages.getGuildInstance(this.guildId);
|
this.savedMessages = GuildSavedMessages.getGuildInstance(this.guildId);
|
||||||
|
this.logs = new GuildLogs(this.guildId);
|
||||||
|
|
||||||
this.onMessageCreateFn = this.onMessageCreate.bind(this);
|
this.onMessageCreateFn = this.onMessageCreate.bind(this);
|
||||||
this.savedMessages.events.on("create", this.onMessageCreateFn);
|
this.savedMessages.events.on("create", this.onMessageCreateFn);
|
||||||
|
@ -332,24 +347,48 @@ export class TagsPlugin extends ZeppelinPlugin<TConfigSchema> {
|
||||||
str: string,
|
str: string,
|
||||||
prefix: string,
|
prefix: string,
|
||||||
tagName: string,
|
tagName: string,
|
||||||
tagBody: string,
|
tagBody: t.TypeOf<typeof Tag>,
|
||||||
member: Member,
|
member: Member,
|
||||||
): Promise<string | null> {
|
): Promise<StrictMessageContent | null> {
|
||||||
const variableStr = str.slice(prefix.length + tagName.length).trim();
|
const variableStr = str.slice(prefix.length + tagName.length).trim();
|
||||||
const tagArgs = parseArguments(variableStr).map(v => v.value);
|
const tagArgs = parseArguments(variableStr).map(v => v.value);
|
||||||
|
|
||||||
// Format the string
|
// Renders strings in objects and arrays recursively, effectively supporting embeds for tags
|
||||||
try {
|
const renderTagValue = async value => {
|
||||||
let rendered = await this.renderTag(tagBody, tagArgs, {
|
if (Array.isArray(value)) {
|
||||||
|
const result = [];
|
||||||
|
for (const item of value) {
|
||||||
|
result.push(await renderTagValue(item));
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
} else if (value == null) {
|
||||||
|
return null;
|
||||||
|
} else if (typeof value === "object") {
|
||||||
|
const result = {};
|
||||||
|
for (const [prop, _value] of Object.entries(value)) {
|
||||||
|
result[prop] = await renderTagValue(_value);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
} else if (typeof value === "string") {
|
||||||
|
return renderTagString(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
return value;
|
||||||
|
};
|
||||||
|
|
||||||
|
const renderTagString = async _str => {
|
||||||
|
let rendered = await this.renderTag(_str, tagArgs, {
|
||||||
member: stripObjectToScalars(member, ["user"]),
|
member: stripObjectToScalars(member, ["user"]),
|
||||||
user: stripObjectToScalars(member.user),
|
user: stripObjectToScalars(member.user),
|
||||||
});
|
});
|
||||||
rendered = rendered.trim();
|
rendered = rendered.trim();
|
||||||
|
|
||||||
if (rendered === "") return;
|
|
||||||
if (rendered.length > 2000) return;
|
|
||||||
|
|
||||||
return rendered;
|
return rendered;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Format the string
|
||||||
|
try {
|
||||||
|
return typeof tagBody === "string" ? { content: await renderTagString(tagBody) } : await renderTagValue(tagBody);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
if (e instanceof TemplateParseError) {
|
if (e instanceof TemplateParseError) {
|
||||||
logger.warn(`Invalid tag format!\nError: ${e.message}\nFormat: ${tagBody}`);
|
logger.warn(`Invalid tag format!\nError: ${e.message}\nFormat: ${tagBody}`);
|
||||||
|
@ -476,6 +515,14 @@ export class TagsPlugin extends ZeppelinPlugin<TConfigSchema> {
|
||||||
|
|
||||||
deleteWithCommand = config.delete_with_command;
|
deleteWithCommand = config.delete_with_command;
|
||||||
|
|
||||||
|
const validationError = await validate(tStrictMessageContent, renderedTag);
|
||||||
|
if (validationError) {
|
||||||
|
this.logs.log(LogType.BOT_ALERT, {
|
||||||
|
body: `Rendering tag ${matchedTagName} resulted in an invalid message: ${validationError.message}`,
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
const channel = this.guild.channels.get(msg.channel_id) as TextChannel;
|
const channel = this.guild.channels.get(msg.channel_id) as TextChannel;
|
||||||
const responseMsg = await channel.createMessage(renderedTag);
|
const responseMsg = await channel.createMessage(renderedTag);
|
||||||
|
|
||||||
|
|
|
@ -195,6 +195,15 @@ export const tEmbed = t.type({
|
||||||
),
|
),
|
||||||
});
|
});
|
||||||
|
|
||||||
|
export type StrictMessageContent = { content?: string; tts?: boolean; disableEveryone?: boolean; embed?: EmbedOptions };
|
||||||
|
|
||||||
|
export const tStrictMessageContent = t.type({
|
||||||
|
content: tNullable(t.string),
|
||||||
|
tts: tNullable(t.boolean),
|
||||||
|
disableEveryone: tNullable(t.boolean),
|
||||||
|
embed: tNullable(tEmbed),
|
||||||
|
});
|
||||||
|
|
||||||
export function dropPropertiesByName(obj, propName) {
|
export function dropPropertiesByName(obj, propName) {
|
||||||
if (obj.hasOwnProperty(propName)) delete obj[propName];
|
if (obj.hasOwnProperty(propName)) delete obj[propName];
|
||||||
for (const value of Object.values(obj)) {
|
for (const value of Object.values(obj)) {
|
||||||
|
@ -1017,8 +1026,6 @@ export async function resolveRoleId(bot: Client, guildId: string, value: string)
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
export type StrictMessageContent = { content?: string; tts?: boolean; disableEveryone?: boolean; embed?: EmbedOptions };
|
|
||||||
|
|
||||||
export async function confirm(bot: Client, channel: TextableChannel, userId: string, content: MessageContent) {
|
export async function confirm(bot: Client, channel: TextableChannel, userId: string, content: MessageContent) {
|
||||||
const msg = await channel.createMessage(content);
|
const msg = await channel.createMessage(content);
|
||||||
const reply = await waitForReaction(bot, msg, ["✅", "❌"], userId);
|
const reply = await waitForReaction(bot, msg, ["✅", "❌"], userId);
|
||||||
|
|
Loading…
Add table
Reference in a new issue