3
0
Fork 0
mirror of https://github.com/ZeppelinBot/Zeppelin.git synced 2025-05-10 12:25:02 +00:00

Update to discord.js v13.8.0, adding support for text-in-voice

This commit is contained in:
Dragory 2022-06-13 21:19:56 +03:00
parent ba78103807
commit b05fbe1d04
No known key found for this signature in database
GPG key ID: 5F387BA66DF8AAC1
32 changed files with 151 additions and 149 deletions

View file

@ -15,7 +15,7 @@ export const NewAutoReactionsCmd = autoReactionsCmd({
usage: "!auto_reactions 629990160477585428 👍 👎",
signature: {
channel: ct.channel(),
channel: ct.guildTextBasedChannel(),
reactions: ct.string({ rest: true }),
},
@ -23,7 +23,7 @@ export const NewAutoReactionsCmd = autoReactionsCmd({
const finalReactions: string[] = [];
const me = pluginData.guild.members.cache.get(pluginData.client.user!.id)!;
const missingPermissions = getMissingChannelPermissions(me, args.channel as GuildChannel, requiredPermissions);
const missingPermissions = getMissingChannelPermissions(me, args.channel, requiredPermissions);
if (missingPermissions) {
sendErrorMessage(
pluginData,

View file

@ -1,4 +1,4 @@
import { GuildChannel, Permissions } from "discord.js";
import { GuildChannel, GuildTextBasedChannel, Permissions } from "discord.js";
import { LogType } from "../../../data/LogType";
import { isDiscordAPIError } from "../../../utils";
import { getMissingChannelPermissions } from "../../../utils/getMissingChannelPermissions";
@ -16,7 +16,10 @@ export const AddReactionsEvt = autoReactionsEvt({
allowSelf: true,
async listener({ pluginData, args: { message } }) {
const channel = await message.guild?.channels.fetch(message.channelId);
const channel = (await message.guild?.channels.fetch(message.channelId)) as
| GuildTextBasedChannel
| null
| undefined;
if (!channel) {
return;
}
@ -37,11 +40,7 @@ export const AddReactionsEvt = autoReactionsEvt({
const me = pluginData.guild.members.cache.get(pluginData.client.user!.id)!;
if (me) {
const missingPermissions = getMissingChannelPermissions(
me,
channel as GuildChannel,
readChannelPermissions | p.ADD_REACTIONS,
);
const missingPermissions = getMissingChannelPermissions(me, channel, readChannelPermissions | p.ADD_REACTIONS);
if (missingPermissions) {
const logs = pluginData.getPlugin(LogsPlugin);
logs.logBotAlert({

View file

@ -38,7 +38,7 @@ export const AlertAction = automodAction({
const channel = pluginData.guild.channels.cache.get(actionConfig.channel as Snowflake);
const logs = pluginData.getPlugin(LogsPlugin);
if (channel && channel instanceof TextChannel) {
if (channel?.isText()) {
const text = actionConfig.text;
const theMessageLink =
contexts[0].message && messageLink(pluginData.guild.id, contexts[0].message.channel_id, contexts[0].message.id);

View file

@ -36,7 +36,7 @@ export const ReplyAction = automodAction({
.filter((c) => c.message?.channel_id)
.filter((c) => {
const channel = pluginData.guild.channels.cache.get(c.message!.channel_id as Snowflake);
return channel instanceof TextChannel || channel instanceof ThreadChannel;
return channel?.isText();
});
const contextsByChannelId = contextsWithTextChannels.reduce((map: Map<string, AutomodContext[]>, context) => {

View file

@ -19,7 +19,7 @@ export function resolveActionContactMethods(
}
const channel = pluginData.guild.channels.cache.get(actionConfig.notifyChannel as Snowflake);
if (!(channel instanceof TextChannel || channel instanceof ThreadChannel)) {
if (!channel?.isText()) {
throw new RecoverablePluginError(ERRORS.INVALID_USER_NOTIFICATION_CHANNEL);
}

View file

@ -1,4 +1,4 @@
import { BaseGuildTextChannel, Snowflake, TextChannel, ThreadChannel } from "discord.js";
import { BaseGuildTextChannel, GuildTextBasedChannel, Snowflake, TextChannel, ThreadChannel } from "discord.js";
import { GuildPluginData } from "knub";
import { channelToTemplateSafeChannel, userToTemplateSafeUser } from "../../../utils/templateSafeObjects";
import { SavedMessage } from "../../../data/entities/SavedMessage";
@ -22,9 +22,7 @@ export async function censorMessage(
}
const user = await resolveUser(pluginData.client, savedMessage.user_id);
const channel = pluginData.guild.channels.resolve(savedMessage.channel_id as Snowflake)! as
| BaseGuildTextChannel
| ThreadChannel;
const channel = pluginData.guild.channels.resolve(savedMessage.channel_id as Snowflake)! as GuildTextBasedChannel;
pluginData.getPlugin(LogsPlugin).logCensor({
user,

View file

@ -20,17 +20,17 @@ export const ViewCounterCmd = typedGuildCommand<CountersPluginType>()({
},
{
counterName: ct.string(),
channel: ct.textChannel(),
channel: ct.guildTextBasedChannel(),
},
{
counterName: ct.string(),
channel: ct.textChannel(),
channel: ct.guildTextBasedChannel(),
user: ct.resolvedUser(),
},
{
counterName: ct.string(),
user: ct.resolvedUser(),
channel: ct.textChannel(),
channel: ct.guildTextBasedChannel(),
},
],
@ -68,7 +68,7 @@ export const ViewCounterCmd = typedGuildCommand<CountersPluginType>()({
}
const potentialChannel = pluginData.guild.channels.resolve(reply.content as Snowflake);
if (!potentialChannel || !(potentialChannel instanceof TextChannel)) {
if (!potentialChannel?.isText()) {
sendErrorMessage(pluginData, message.channel, "Channel is not a text channel, cancelling");
return;
}

View file

@ -1,11 +1,11 @@
import { GuildPluginData } from "knub";
import { InternalPosterPluginType } from "../types";
import { NewsChannel, TextChannel, WebhookClient } from "discord.js";
import { getOrCreateWebhookForChannel } from "./getOrCreateWebhookForChannel";
import { WebhookClient } from "discord.js";
import { getOrCreateWebhookForChannel, WebhookableChannel } from "./getOrCreateWebhookForChannel";
export async function getOrCreateWebhookClientForChannel(
pluginData: GuildPluginData<InternalPosterPluginType>,
channel: TextChannel | NewsChannel,
channel: WebhookableChannel,
): Promise<WebhookClient | null> {
if (!pluginData.state.webhookClientCache.has(channel.id)) {
const webhookInfo = await getOrCreateWebhookForChannel(pluginData, channel);

View file

@ -1,17 +1,20 @@
import { GuildPluginData } from "knub";
import { InternalPosterPluginType } from "../types";
import { NewsChannel, Permissions, TextChannel } from "discord.js";
import { AnyChannel, GuildChannel, MessageManager, NewsChannel, Permissions, TextChannel } from "discord.js";
import { isDiscordAPIError } from "../../../utils";
type WebhookInfo = [id: string, token: string];
export type WebhookableChannel = Extract<AnyChannel, { createWebhook: (...args: any[]) => any }>;
export function channelIsWebhookable(channel: AnyChannel): channel is WebhookableChannel {
return "createWebhook" in channel;
}
export async function getOrCreateWebhookForChannel(
pluginData: GuildPluginData<InternalPosterPluginType>,
channel: TextChannel | NewsChannel,
channel: WebhookableChannel,
): Promise<WebhookInfo | null> {
// tslint:disable-next-line:no-console FIXME: Here for debugging purposes
console.log(`getOrCreateWebhookForChannel(${channel.id})`);
// Database cache
const fromDb = await pluginData.state.webhooks.findByChannelId(channel.id);
if (fromDb) {

View file

@ -1,7 +1,7 @@
import { Message, MessageOptions, NewsChannel, TextChannel, WebhookClient } from "discord.js";
import { GuildTextBasedChannel, Message, MessageOptions, NewsChannel, TextChannel, WebhookClient } from "discord.js";
import { GuildPluginData } from "knub";
import { InternalPosterPluginType } from "../types";
import { getOrCreateWebhookForChannel } from "./getOrCreateWebhookForChannel";
import { channelIsWebhookable, getOrCreateWebhookForChannel } from "./getOrCreateWebhookForChannel";
import { APIMessage } from "discord-api-types";
import { isDiscordAPIError } from "../../../utils";
import { getOrCreateWebhookClientForChannel } from "./getOrCreateWebhookClientForChannel";
@ -12,7 +12,7 @@ export type InternalPosterMessageResult = {
};
async function sendDirectly(
channel: TextChannel | NewsChannel,
channel: GuildTextBasedChannel,
content: MessageOptions,
): Promise<InternalPosterMessageResult | null> {
return channel.send(content).then((message) => ({
@ -26,17 +26,26 @@ async function sendDirectly(
*/
export async function sendMessage(
pluginData: GuildPluginData<InternalPosterPluginType>,
channel: TextChannel | NewsChannel,
channel: GuildTextBasedChannel,
content: MessageOptions,
): Promise<InternalPosterMessageResult | null> {
return pluginData.state.queue.add(async () => {
const webhookClient = await getOrCreateWebhookClientForChannel(pluginData, channel);
let webhookClient: WebhookClient | null = null;
let threadId: string | undefined;
if (channelIsWebhookable(channel)) {
webhookClient = await getOrCreateWebhookClientForChannel(pluginData, channel);
} else if (channel.isThread() && channelIsWebhookable(channel.parent!)) {
webhookClient = await getOrCreateWebhookClientForChannel(pluginData, channel.parent!);
threadId = channel.id;
}
if (!webhookClient) {
return sendDirectly(channel, content);
}
return webhookClient
.send({
threadId,
...content,
...(pluginData.client.user && {
username: pluginData.client.user.username,
@ -50,7 +59,7 @@ export async function sendMessage(
.catch(async (err) => {
// Unknown Webhook
if (isDiscordAPIError(err) && err.code === 10015) {
await pluginData.state.webhooks.delete(webhookClient.id);
await pluginData.state.webhooks.delete(webhookClient!.id);
pluginData.state.webhookClientCache.delete(channel.id);
// Fallback to regular message for this log message

View file

@ -3,7 +3,7 @@ import { LogsPluginType } from "../types";
import { LogType } from "../../../data/LogType";
import { log } from "../util/log";
import { createTypedTemplateSafeValueContainer } from "../../../templateFormatter";
import { BaseGuildTextChannel, ThreadChannel, User } from "discord.js";
import { BaseGuildTextChannel, GuildTextBasedChannel, ThreadChannel, User } from "discord.js";
import {
channelToTemplateSafeChannel,
savedMessageToTemplateSafeSavedMessage,
@ -15,7 +15,7 @@ import { deactivateMentions, disableCodeBlocks } from "knub/dist/helpers";
interface LogCensorData {
user: User | UnknownUser;
channel: BaseGuildTextChannel | ThreadChannel;
channel: GuildTextBasedChannel;
reason: string;
message: SavedMessage;
}

View file

@ -3,7 +3,7 @@ import { FORMAT_NO_TIMESTAMP, LogsPluginType } from "../types";
import { LogType } from "../../../data/LogType";
import { log } from "../util/log";
import { createTypedTemplateSafeValueContainer } from "../../../templateFormatter";
import { BaseGuildTextChannel, ThreadChannel, User } from "discord.js";
import { BaseGuildTextChannel, GuildTextBasedChannel, ThreadChannel, User } from "discord.js";
import {
channelToTemplateSafeChannel,
savedMessageToTemplateSafeSavedMessage,
@ -16,7 +16,7 @@ import { UnknownUser, useMediaUrls } from "../../../utils";
interface LogMessageDeleteData {
user: User | UnknownUser;
channel: BaseGuildTextChannel | ThreadChannel;
channel: GuildTextBasedChannel;
message: SavedMessage;
}

View file

@ -3,12 +3,12 @@ import { LogsPluginType } from "../types";
import { LogType } from "../../../data/LogType";
import { log } from "../util/log";
import { createTypedTemplateSafeValueContainer } from "../../../templateFormatter";
import { BaseGuildTextChannel, ThreadChannel } from "discord.js";
import { BaseGuildTextChannel, GuildTextBasedChannel, ThreadChannel } from "discord.js";
import { channelToTemplateSafeChannel } from "../../../utils/templateSafeObjects";
interface LogMessageDeleteBareData {
messageId: string;
channel: BaseGuildTextChannel | ThreadChannel;
channel: GuildTextBasedChannel;
}
export function logMessageDeleteBare(pluginData: GuildPluginData<LogsPluginType>, data: LogMessageDeleteBareData) {

View file

@ -3,13 +3,13 @@ import { LogsPluginType } from "../types";
import { LogType } from "../../../data/LogType";
import { log } from "../util/log";
import { createTypedTemplateSafeValueContainer } from "../../../templateFormatter";
import { BaseGuildTextChannel, ThreadChannel } from "discord.js";
import { BaseGuildTextChannel, GuildTextBasedChannel, ThreadChannel } from "discord.js";
import { channelToTemplateSafeChannel } from "../../../utils/templateSafeObjects";
interface LogMessageDeleteBulkData {
count: number;
authorIds: string[];
channel: BaseGuildTextChannel | ThreadChannel;
channel: GuildTextBasedChannel;
archiveUrl: string;
}

View file

@ -3,7 +3,7 @@ import { LogsPluginType } from "../types";
import { LogType } from "../../../data/LogType";
import { log } from "../util/log";
import { createTypedTemplateSafeValueContainer } from "../../../templateFormatter";
import { BaseGuildTextChannel, ThreadChannel, User } from "discord.js";
import { BaseGuildTextChannel, GuildTextBasedChannel, ThreadChannel, User } from "discord.js";
import {
channelToTemplateSafeChannel,
savedMessageToTemplateSafeSavedMessage,
@ -14,7 +14,7 @@ import { UnknownUser } from "../../../utils";
interface LogMessageEditData {
user: User | UnknownUser;
channel: BaseGuildTextChannel | ThreadChannel;
channel: GuildTextBasedChannel;
before: SavedMessage;
after: SavedMessage;
}

View file

@ -3,12 +3,12 @@ import { LogsPluginType } from "../types";
import { LogType } from "../../../data/LogType";
import { log } from "../util/log";
import { createTypedTemplateSafeValueContainer } from "../../../templateFormatter";
import { BaseGuildTextChannel, ThreadChannel, User } from "discord.js";
import { BaseGuildTextChannel, GuildTextBasedChannel, ThreadChannel, User } from "discord.js";
import { channelToTemplateSafeChannel, userToTemplateSafeUser } from "../../../utils/templateSafeObjects";
interface LogPostedScheduledMessageData {
author: User;
channel: BaseGuildTextChannel | ThreadChannel;
channel: GuildTextBasedChannel;
messageId: string;
}

View file

@ -3,12 +3,12 @@ import { LogsPluginType } from "../types";
import { LogType } from "../../../data/LogType";
import { log } from "../util/log";
import { createTypedTemplateSafeValueContainer } from "../../../templateFormatter";
import { BaseGuildTextChannel, ThreadChannel, User } from "discord.js";
import { BaseGuildTextChannel, GuildTextBasedChannel, ThreadChannel, User } from "discord.js";
import { channelToTemplateSafeChannel, userToTemplateSafeUser } from "../../../utils/templateSafeObjects";
interface LogRepeatedMessageData {
author: User;
channel: BaseGuildTextChannel | ThreadChannel;
channel: GuildTextBasedChannel;
datetime: string;
date: string;
time: string;

View file

@ -3,12 +3,12 @@ import { LogsPluginType } from "../types";
import { LogType } from "../../../data/LogType";
import { log } from "../util/log";
import { createTypedTemplateSafeValueContainer } from "../../../templateFormatter";
import { BaseGuildTextChannel, ThreadChannel, User } from "discord.js";
import { BaseGuildTextChannel, GuildTextBasedChannel, ThreadChannel, User } from "discord.js";
import { channelToTemplateSafeChannel, userToTemplateSafeUser } from "../../../utils/templateSafeObjects";
interface LogScheduledMessageData {
author: User;
channel: BaseGuildTextChannel | ThreadChannel;
channel: GuildTextBasedChannel;
datetime: string;
date: string;
time: string;

View file

@ -3,12 +3,12 @@ import { LogsPluginType } from "../types";
import { LogType } from "../../../data/LogType";
import { log } from "../util/log";
import { createTypedTemplateSafeValueContainer } from "../../../templateFormatter";
import { BaseGuildTextChannel, ThreadChannel, User } from "discord.js";
import { BaseGuildTextChannel, GuildTextBasedChannel, ThreadChannel, User } from "discord.js";
import { channelToTemplateSafeChannel, userToTemplateSafeUser } from "../../../utils/templateSafeObjects";
interface LogScheduledRepeatedMessageData {
author: User;
channel: BaseGuildTextChannel | ThreadChannel;
channel: GuildTextBasedChannel;
datetime: string;
date: string;
time: string;

View file

@ -83,7 +83,7 @@ export async function log<TLogType extends keyof ILogTypeData>(
logChannelLoop: for (const [channelId, opts] of Object.entries(logChannels)) {
const channel = pluginData.guild.channels.cache.get(channelId as Snowflake);
if (!channel || !(channel instanceof TextChannel)) continue;
if (!channel?.isText()) continue;
if (pluginData.state.channelCooldowns.isOnCooldown(channelId)) continue;
if (opts.include?.length && !opts.include.includes(typeStr)) continue;
if (opts.exclude && opts.exclude.includes(typeStr)) continue;

View file

@ -1,4 +1,4 @@
import { BaseGuildTextChannel, Snowflake, ThreadChannel } from "discord.js";
import { BaseGuildTextChannel, GuildTextBasedChannel, Snowflake, ThreadChannel } from "discord.js";
import { GuildPluginData } from "knub";
import { SavedMessage } from "../../../data/entities/SavedMessage";
import { LogType } from "../../../data/LogType";
@ -12,9 +12,9 @@ export async function onMessageDeleteBulk(pluginData: GuildPluginData<LogsPlugin
return;
}
const channel = pluginData.guild.channels.cache.get(savedMessages[0].channel_id as Snowflake) as
| BaseGuildTextChannel
| ThreadChannel;
const channel = pluginData.guild.channels.cache.get(
savedMessages[0].channel_id as Snowflake,
) as GuildTextBasedChannel;
const archiveId = await pluginData.state.archives.createFromSavedMessages(savedMessages, pluginData.guild);
const archiveUrl = pluginData.state.archives.getUrl(getBaseUrl(pluginData), archiveId);
const authorIds = Array.from(new Set(savedMessages.map((item) => `\`${item.user_id}\``)));

View file

@ -1,4 +1,4 @@
import { BaseGuildTextChannel, MessageEmbed, Snowflake, ThreadChannel } from "discord.js";
import { BaseGuildTextChannel, GuildTextBasedChannel, MessageEmbed, Snowflake, ThreadChannel } from "discord.js";
import { GuildPluginData } from "knub";
import cloneDeep from "lodash.clonedeep";
import { channelToTemplateSafeChannel, userToTemplateSafeUser } from "../../../utils/templateSafeObjects";
@ -49,9 +49,7 @@ export async function onMessageUpdate(
}
const user = await resolveUser(pluginData.client, savedMessage.user_id);
const channel = pluginData.guild.channels.resolve(savedMessage.channel_id as Snowflake)! as
| BaseGuildTextChannel
| ThreadChannel;
const channel = pluginData.guild.channels.resolve(savedMessage.channel_id as Snowflake)! as GuildTextBasedChannel;
logMessageEdit(pluginData, {
user,

View file

@ -183,9 +183,10 @@ export async function muteUser(
}
const useChannel = existingMute ? config.message_on_update : config.message_on_mute;
const channel =
config.message_channel && pluginData.guild.channels.cache.get(config.message_channel as Snowflake);
if (useChannel && channel instanceof TextChannel) {
const channel = config.message_channel
? pluginData.guild.channels.cache.get(config.message_channel as Snowflake)
: null;
if (useChannel && channel?.isText()) {
contactMethods.push({ type: "channel", channel });
}
}

View file

@ -1,4 +1,4 @@
import { Channel, Message, NewsChannel, TextChannel, ThreadChannel } from "discord.js";
import { Channel, GuildTextBasedChannel, Message, NewsChannel, TextChannel, ThreadChannel } from "discord.js";
import humanizeDuration from "humanize-duration";
import { GuildPluginData } from "knub";
import moment from "moment-timezone";
@ -20,7 +20,7 @@ const MAX_REPEAT_UNTIL = moment.utc().add(100, "years");
export async function actualPostCmd(
pluginData: GuildPluginData<PostPluginType>,
msg: Message,
targetChannel: Channel,
targetChannel: GuildTextBasedChannel,
content: StrictMessageContent,
opts: {
"enable-mentions"?: boolean;
@ -30,12 +30,8 @@ export async function actualPostCmd(
"repeat-times"?: number;
} = {},
) {
if (
!(targetChannel instanceof TextChannel) &&
!(targetChannel instanceof NewsChannel) &&
!(targetChannel instanceof ThreadChannel)
) {
msg.channel.send(errorMessage("Specified channel is not a text channel, announcement channel, or thread"));
if (!targetChannel.isText()) {
msg.channel.send(errorMessage("Specified channel is not a text-based channel"));
return;
}

View file

@ -1,4 +1,12 @@
import { Message, MessageAttachment, MessageOptions, NewsChannel, TextChannel, ThreadChannel } from "discord.js";
import {
GuildTextBasedChannel,
Message,
MessageAttachment,
MessageOptions,
NewsChannel,
TextChannel,
ThreadChannel,
} from "discord.js";
import fs from "fs";
import { GuildPluginData } from "knub";
import { downloadFile } from "../../../utils";
@ -9,7 +17,7 @@ const fsp = fs.promises;
export async function postMessage(
pluginData: GuildPluginData<PostPluginType>,
channel: TextChannel | NewsChannel | ThreadChannel,
channel: GuildTextBasedChannel,
content: MessageOptions,
attachments: MessageAttachment[] = [],
enableMentions: boolean = false,