From 5a5fe4869efeaf54d7c4cfbb17f85bbec65e0c6a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nils=20Bl=C3=B6meke?= Date: Mon, 14 Oct 2019 01:24:20 +0200 Subject: [PATCH] Working starboards Fixed issue with default config not being applied and links not being recognized properly. --- src/plugins/Starboard.ts | 115 +++++++++++++++++++++++++++++++-------- src/utils.ts | 2 +- 2 files changed, 94 insertions(+), 23 deletions(-) diff --git a/src/plugins/Starboard.ts b/src/plugins/Starboard.ts index 8141e366..8181becd 100644 --- a/src/plugins/Starboard.ts +++ b/src/plugins/Starboard.ts @@ -1,5 +1,5 @@ import { decorators as d, IPluginOptions } from "knub"; -import { ZeppelinPlugin } from "./ZeppelinPlugin"; +import { ZeppelinPlugin, trimPluginDescription } from "./ZeppelinPlugin"; import { GuildChannel, Message, TextChannel } from "eris"; import { errorMessage, getUrlsInString, noop, successMessage, tNullable } from "../utils"; import path from "path"; @@ -8,7 +8,7 @@ import { GuildSavedMessages } from "../data/GuildSavedMessages"; import { SavedMessage } from "../data/entities/SavedMessage"; import * as t from "io-ts"; import { GuildStarboardMessages } from "../data/GuildStarboardMessages"; -import { StarboardMessage } from "src/data/entities/StarboardMessage"; +import { StarboardMessage } from "../data/entities/StarboardMessage"; const StarboardOpts = t.type({ source_channel_ids: t.array(t.string), @@ -16,7 +16,6 @@ const StarboardOpts = t.type({ positive_emojis: tNullable(t.array(t.string)), positive_required: tNullable(t.number), allow_multistar: tNullable(t.boolean), - negative_emojis: tNullable(t.array(t.string)), enabled: tNullable(t.boolean), }); type TStarboardOpts = t.TypeOf; @@ -32,7 +31,6 @@ const defaultStarboardOpts: Partial = { positive_emojis: ["⭐"], positive_required: 5, allow_multistar: false, - negative_emojis: [], enabled: true, }; @@ -41,6 +39,57 @@ export class StarboardPlugin extends ZeppelinPlugin { public static showInDocs = false; public static configSchema = ConfigSchema; + public static pluginInfo = { + prettyName: "Starboards", + description: trimPluginDescription(` + This plugin contains all functionality needed to use discord channels as starboards. + `), + configurationGuide: trimPluginDescription(` + You can customize multiple settings for starboards. + Any emoji that you want available needs to be put into the config in its raw form. + To obtain a raw form of an emoji, please write out the emoji and put a backslash in front of it. + Example with default emoji: "\:star:" => "⭐" + Example with custom emoji: "\:mrvnSmile:" => "<:mrvnSmile:543000534102310933>" + Now, past the result into the config, but make sure to exclude all less-than and greater-than signs like in the second example. + + + ### Simple starboard with one source channel + All messages in the source channel that get enough positive reactions will be posted into the starboard channel. + The only positive reaction counted here is the default emoji "⭐". + Multistars are not allowed, meaning only one reaction is counted from the same user. + + ~~~yml + starboard: + config: + entries: + exampleOne: + source_channel_ids: ["604342623569707010"] + starboard_channel_id: "604342689038729226" + positive_emojis: ["⭐"] + positive_required: 5 + enabled: true + ~~~ + + ### Starboard with two sources and two emoji + All messages in any of the source channels that get enough positive reactions will be posted into the starboard channel. + Both the default emoji "⭐" and the custom emoji ":mrvnSmile:543000534102310933" are counted. + Multistars are allowed, so a user can react with both emoji and be counted twice. + + ~~~yml + starboard: + config: + entries: + exampleTwo: + source_channel_ids: ["604342623569707010", "604342649251561487"] + starboard_channel_id: "604342689038729226" + positive_emojis: ["⭐", ":mrvnSmile:543000534102310933"] + positive_required: 10 + allow_multistar: true + enabled: true + ~~~ + `), + }; + protected savedMessages: GuildSavedMessages; protected starboardMessages: GuildStarboardMessages; @@ -64,18 +113,32 @@ export class StarboardPlugin extends ZeppelinPlugin { }; } - protected getStarboardOptsForSourceChannelId(sourceChannel): TStarboardOpts[] { + protected getStarboardOptsForSourceChannel(sourceChannel): TStarboardOpts[] { const config = this.getConfigForChannel(sourceChannel); - return Object.values(config.entries) - .filter(opts => opts.source_channel_ids.includes(sourceChannel.id)) - .map(opts => Object.assign({}, defaultStarboardOpts, opts)); + + const configs = Object.values(config.entries).filter(opts => opts.source_channel_ids.includes(sourceChannel.id)); + configs.forEach(cfg => { + if (cfg.allow_multistar == null) cfg.allow_multistar = defaultStarboardOpts.allow_multistar; + if (cfg.enabled == null) cfg.enabled = defaultStarboardOpts.enabled; + if (cfg.positive_emojis == null) cfg.positive_emojis = defaultStarboardOpts.positive_emojis; + if (cfg.positive_required == null) cfg.positive_required = defaultStarboardOpts.positive_required; + }); + + return configs; } - protected getStarboardOptsForStarboardChannelId(starboardChannel): TStarboardOpts[] { + protected getStarboardOptsForStarboardChannel(starboardChannel): TStarboardOpts[] { const config = this.getConfigForChannel(starboardChannel); - return Object.values(config.entries) - .filter(opts => opts.starboard_channel_id === starboardChannel.id) - .map(opts => Object.assign({}, defaultStarboardOpts, opts)); + + const configs = Object.values(config.entries).filter(opts => opts.starboard_channel_id === starboardChannel.id); + configs.forEach(cfg => { + if (cfg.allow_multistar == null) cfg.allow_multistar = defaultStarboardOpts.allow_multistar; + if (cfg.enabled == null) cfg.enabled = defaultStarboardOpts.enabled; + if (cfg.positive_emojis == null) cfg.positive_emojis = defaultStarboardOpts.positive_emojis; + if (cfg.positive_required == null) cfg.positive_required = defaultStarboardOpts.positive_required; + }); + + return configs; } onLoad() { @@ -107,7 +170,7 @@ export class StarboardPlugin extends ZeppelinPlugin { } } - const applicableStarboards = await this.getStarboardOptsForSourceChannelId(msg.channel); + const applicableStarboards = await this.getStarboardOptsForSourceChannel(msg.channel); for (const starboard of applicableStarboards) { // Instantly continue if the starboard is disabled @@ -133,7 +196,6 @@ export class StarboardPlugin extends ZeppelinPlugin { */ async countReactions(msg: Message, counted: string[], countDouble: boolean) { let totalCount = []; - countDouble = countDouble || false; for (const emoji of counted) { totalCount = await this.countReactionsForEmoji(msg, emoji, totalCount, countDouble); @@ -243,7 +305,7 @@ export class StarboardPlugin extends ZeppelinPlugin { if (messages.length > 0) { for (const starboardMessage of messages) { if (!starboardMessage.starboard_message_id) continue; - this.removeMessageFromStarboard(starboardMessage); + this.removeMessageFromStarboard(starboardMessage).catch(noop); } } else { messages = await this.starboardMessages.getStarboardMessagesForStarboardMessageId(msg.id); @@ -254,27 +316,36 @@ export class StarboardPlugin extends ZeppelinPlugin { this.removeMessageFromStarboardMessages( starboardMessage.starboard_message_id, starboardMessage.starboard_channel_id, - ); + ).catch(noop); } } } - @d.command("starboard migrate_pins", " ") + @d.command("starboard migrate_pins", " ", { + extra: { + info: { + description: + "Migrates all of a channels pins to starboard messages, posting them in the starboard channel. The old pins are not unpinned.", + }, + }, + }) async migratePinsCmd(msg: Message, args: { pinChannelId: string; starboardChannelId }) { try { - const starboards = await this.getStarboardOptsForStarboardChannelId(this.bot.getChannel(args.starboardChannelId)); + const starboards = await this.getStarboardOptsForStarboardChannel(this.bot.getChannel(args.starboardChannelId)); if (!starboards) { - msg.channel.createMessage(errorMessage("The specified channel doesn't have a starboard!")); + msg.channel.createMessage(errorMessage("The specified channel doesn't have a starboard!")).catch(noop); return; } const channel = (await this.guild.channels.get(args.pinChannelId)) as GuildChannel & TextChannel; if (!channel) { - msg.channel.createMessage(errorMessage("Could not find the specified channel to migrate pins from!")); + msg.channel + .createMessage(errorMessage("Could not find the specified channel to migrate pins from!")) + .catch(noop); return; } - msg.channel.createMessage(`Migrating pins from <#${channel.id}> to <#${args.starboardChannelId}>...`); + msg.channel.createMessage(`Migrating pins from <#${channel.id}> to <#${args.starboardChannelId}>...`).catch(noop); const pins = await channel.getPins(); pins.reverse(); // Migrate pins starting from the oldest message @@ -288,7 +359,7 @@ export class StarboardPlugin extends ZeppelinPlugin { await this.saveMessageToStarboard(pin, args.starboardChannelId); } - msg.channel.createMessage(successMessage("Pins migrated!")); + msg.channel.createMessage(successMessage("Pins migrated!")).catch(noop); } catch (error) { this.sendErrorMessage( msg.channel, diff --git a/src/utils.ts b/src/utils.ts index dee6b8d9..b04d25e3 100644 --- a/src/utils.ts +++ b/src/utils.ts @@ -189,7 +189,7 @@ const urlRegex = /(\S+\.\S+)/g; const protocolRegex = /^[a-z]+:\/\//; export function getUrlsInString(str: string, unique = false): url.URL[] { - let matches = (str.match(urlRegex) || []).map(m => m[0]); + let matches = str.match(urlRegex) || []; if (unique) matches = Array.from(new Set(matches)); return matches.reduce((urls, match) => {