mirror of
https://github.com/ZeppelinBot/Zeppelin.git
synced 2025-05-10 12:25:02 +00:00
ReactionRoles: only require message id; allow use of emojis from other (shared) servers; add !reaction_roles clear command
This commit is contained in:
parent
21a357f8c5
commit
52db74005b
1 changed files with 55 additions and 47 deletions
|
@ -1,77 +1,85 @@
|
|||
import { Plugin, decorators as d } from "knub";
|
||||
import { CustomEmoji, errorMessage, isSnowflake } from "../utils";
|
||||
import { decorators as d } from "knub";
|
||||
import { CustomEmoji, errorMessage, isSnowflake, successMessage } from "../utils";
|
||||
import { GuildReactionRoles } from "../data/GuildReactionRoles";
|
||||
import { Channel, Message, TextChannel } from "eris";
|
||||
import { ZeppelinPlugin } from "./ZeppelinPlugin";
|
||||
import { GuildSavedMessages } from "../data/GuildSavedMessages";
|
||||
|
||||
type ReactionRolePair = [string, string, string?];
|
||||
|
||||
export class ReactionRolesPlugin extends Plugin {
|
||||
export class ReactionRolesPlugin extends ZeppelinPlugin {
|
||||
public static pluginName = "reaction_roles";
|
||||
|
||||
protected reactionRoles: GuildReactionRoles;
|
||||
protected savedMessages: GuildSavedMessages;
|
||||
|
||||
getDefaultOptions() {
|
||||
return {
|
||||
permissions: {
|
||||
manage: false
|
||||
manage: false,
|
||||
},
|
||||
|
||||
overrides: [
|
||||
{
|
||||
level: ">=100",
|
||||
permissions: {
|
||||
manage: true
|
||||
}
|
||||
}
|
||||
]
|
||||
manage: true,
|
||||
},
|
||||
},
|
||||
],
|
||||
};
|
||||
}
|
||||
|
||||
async onLoad() {
|
||||
this.reactionRoles = GuildReactionRoles.getInstance(this.guildId);
|
||||
return;
|
||||
|
||||
// Pre-fetch all messages with reaction roles so we get their events
|
||||
const reactionRoles = await this.reactionRoles.all();
|
||||
|
||||
const channelMessages: Map<string, Set<string>> = reactionRoles.reduce((map: Map<string, Set<string>>, row) => {
|
||||
if (!map.has(row.channel_id)) map.set(row.channel_id, new Set());
|
||||
map.get(row.channel_id).add(row.message_id);
|
||||
return map;
|
||||
}, new Map());
|
||||
|
||||
const msgLoadPromises = [];
|
||||
|
||||
for (const [channelId, messageIdSet] of channelMessages.entries()) {
|
||||
const messageIds = Array.from(messageIdSet.values());
|
||||
const channel = (await this.guild.channels.get(channelId)) as TextChannel;
|
||||
if (!channel) continue;
|
||||
|
||||
for (const messageId of messageIds) {
|
||||
msgLoadPromises.push(channel.getMessage(messageId));
|
||||
}
|
||||
}
|
||||
|
||||
await Promise.all(msgLoadPromises);
|
||||
this.savedMessages = GuildSavedMessages.getInstance(this.guildId);
|
||||
}
|
||||
|
||||
@d.command("reaction_roles", "<channel:channel> <messageId:string> <reactionRolePairs:string$>")
|
||||
@d.command("reaction_roles clear", "<messageId:string>")
|
||||
@d.permission("manage")
|
||||
async reactionRolesCmd(msg: Message, args: { channel: Channel; messageId: string; reactionRolePairs: string }) {
|
||||
if (!(args.channel instanceof TextChannel)) {
|
||||
msg.channel.createMessage(errorMessage("Channel must be a text channel!"));
|
||||
async clearReactionRolesCmd(msg: Message, args: { messageId: string }) {
|
||||
const savedMessage = await this.savedMessages.find(args.messageId);
|
||||
if (!savedMessage) {
|
||||
msg.channel.createMessage(errorMessage("Unknown message"));
|
||||
return;
|
||||
}
|
||||
|
||||
const targetMessage = await args.channel.getMessage(args.messageId);
|
||||
const existingReactionRoles = this.reactionRoles.getForMessage(args.messageId);
|
||||
if (!existingReactionRoles) {
|
||||
msg.channel.createMessage(errorMessage("Message doesn't have reaction roles on it"));
|
||||
return;
|
||||
}
|
||||
|
||||
this.reactionRoles.removeFromMessage(args.messageId);
|
||||
|
||||
const channel = this.guild.channels.get(savedMessage.channel_id) as TextChannel;
|
||||
const targetMessage = await channel.getMessage(savedMessage.id);
|
||||
await targetMessage.removeReactions();
|
||||
|
||||
msg.channel.createMessage(successMessage("Reaction roles cleared"));
|
||||
}
|
||||
|
||||
@d.command("reaction_roles", "<messageId:string> <reactionRolePairs:string$>")
|
||||
@d.permission("manage")
|
||||
async reactionRolesCmd(msg: Message, args: { messageId: string; reactionRolePairs: string }) {
|
||||
const savedMessage = await this.savedMessages.find(args.messageId);
|
||||
if (!savedMessage) {
|
||||
msg.channel.createMessage(errorMessage("Unknown message"));
|
||||
return;
|
||||
}
|
||||
|
||||
const channel = await this.guild.channels.get(savedMessage.channel_id);
|
||||
if (!channel || !(channel instanceof TextChannel)) {
|
||||
msg.channel.createMessage(errorMessage("Channel no longer exists"));
|
||||
return;
|
||||
}
|
||||
|
||||
const targetMessage = await channel.getMessage(args.messageId);
|
||||
if (!targetMessage) {
|
||||
args.channel.createMessage(errorMessage("Unknown message!"));
|
||||
msg.channel.createMessage(errorMessage("Unknown message (2)"));
|
||||
return;
|
||||
}
|
||||
|
||||
const guildEmojis = this.guild.emojis as CustomEmoji[];
|
||||
const guildEmojiIds = guildEmojis.map(e => e.id);
|
||||
|
||||
// Turn "emoji = role" pairs into an array of tuples of the form [emoji, roleId]
|
||||
// Emoji is either a unicode emoji or the snowflake of a custom emoji
|
||||
const newRolePairs: ReactionRolePair[] = args.reactionRolePairs
|
||||
|
@ -86,13 +94,13 @@ export class ReactionRolesPlugin extends Plugin {
|
|||
} else {
|
||||
return pair as ReactionRolePair;
|
||||
}
|
||||
}
|
||||
},
|
||||
);
|
||||
|
||||
// Verify the specified emojis and roles are valid
|
||||
for (const pair of newRolePairs) {
|
||||
if (isSnowflake(pair[0]) && !guildEmojiIds.includes(pair[0])) {
|
||||
msg.channel.createMessage(errorMessage("I can only use regular emojis and custom emojis from this server"));
|
||||
if (!this.canUseEmoji(pair[0])) {
|
||||
msg.channel.createMessage(errorMessage("I can only use regular emojis and custom emojis from servers I'm on"));
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -107,7 +115,7 @@ export class ReactionRolesPlugin extends Plugin {
|
|||
|
||||
// Remove old reaction/role pairs that weren't included in the new pairs or were changed in some way
|
||||
const toRemove = oldRolePairs.filter(
|
||||
pair => !newRolePairs.find(oldPair => oldPair[0] === pair[0] && oldPair[1] === pair[1])
|
||||
pair => !newRolePairs.find(oldPair => oldPair[0] === pair[0] && oldPair[1] === pair[1]),
|
||||
);
|
||||
for (const rolePair of toRemove) {
|
||||
await this.reactionRoles.removeFromMessage(targetMessage.id, rolePair[0]);
|
||||
|
@ -123,7 +131,7 @@ export class ReactionRolesPlugin extends Plugin {
|
|||
|
||||
// Add new/changed reaction/role pairs
|
||||
const toAdd = newRolePairs.filter(
|
||||
pair => !oldRolePairs.find(oldPair => oldPair[0] === pair[0] && oldPair[1] === pair[1])
|
||||
pair => !oldRolePairs.find(oldPair => oldPair[0] === pair[0] && oldPair[1] === pair[1]),
|
||||
);
|
||||
for (const rolePair of toAdd) {
|
||||
let emoji;
|
||||
|
@ -137,7 +145,7 @@ export class ReactionRolesPlugin extends Plugin {
|
|||
}
|
||||
|
||||
await targetMessage.addReaction(emoji);
|
||||
await this.reactionRoles.add(args.channel.id, targetMessage.id, rolePair[0], rolePair[1]);
|
||||
await this.reactionRoles.add(channel.id, targetMessage.id, rolePair[0], rolePair[1]);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue