mirror of
https://github.com/ZeppelinBot/Zeppelin.git
synced 2025-05-18 07:35:02 +00:00
Working starboards
Fixed issue with default config not being applied and links not being recognized properly.
This commit is contained in:
parent
f8736f9139
commit
5a5fe4869e
2 changed files with 94 additions and 23 deletions
|
@ -1,5 +1,5 @@
|
||||||
import { decorators as d, IPluginOptions } from "knub";
|
import { decorators as d, IPluginOptions } from "knub";
|
||||||
import { ZeppelinPlugin } from "./ZeppelinPlugin";
|
import { ZeppelinPlugin, trimPluginDescription } from "./ZeppelinPlugin";
|
||||||
import { GuildChannel, Message, TextChannel } from "eris";
|
import { GuildChannel, Message, TextChannel } from "eris";
|
||||||
import { errorMessage, getUrlsInString, noop, successMessage, tNullable } from "../utils";
|
import { errorMessage, getUrlsInString, noop, successMessage, tNullable } from "../utils";
|
||||||
import path from "path";
|
import path from "path";
|
||||||
|
@ -8,7 +8,7 @@ import { GuildSavedMessages } from "../data/GuildSavedMessages";
|
||||||
import { SavedMessage } from "../data/entities/SavedMessage";
|
import { SavedMessage } from "../data/entities/SavedMessage";
|
||||||
import * as t from "io-ts";
|
import * as t from "io-ts";
|
||||||
import { GuildStarboardMessages } from "../data/GuildStarboardMessages";
|
import { GuildStarboardMessages } from "../data/GuildStarboardMessages";
|
||||||
import { StarboardMessage } from "src/data/entities/StarboardMessage";
|
import { StarboardMessage } from "../data/entities/StarboardMessage";
|
||||||
|
|
||||||
const StarboardOpts = t.type({
|
const StarboardOpts = t.type({
|
||||||
source_channel_ids: t.array(t.string),
|
source_channel_ids: t.array(t.string),
|
||||||
|
@ -16,7 +16,6 @@ const StarboardOpts = t.type({
|
||||||
positive_emojis: tNullable(t.array(t.string)),
|
positive_emojis: tNullable(t.array(t.string)),
|
||||||
positive_required: tNullable(t.number),
|
positive_required: tNullable(t.number),
|
||||||
allow_multistar: tNullable(t.boolean),
|
allow_multistar: tNullable(t.boolean),
|
||||||
negative_emojis: tNullable(t.array(t.string)),
|
|
||||||
enabled: tNullable(t.boolean),
|
enabled: tNullable(t.boolean),
|
||||||
});
|
});
|
||||||
type TStarboardOpts = t.TypeOf<typeof StarboardOpts>;
|
type TStarboardOpts = t.TypeOf<typeof StarboardOpts>;
|
||||||
|
@ -32,7 +31,6 @@ const defaultStarboardOpts: Partial<TStarboardOpts> = {
|
||||||
positive_emojis: ["⭐"],
|
positive_emojis: ["⭐"],
|
||||||
positive_required: 5,
|
positive_required: 5,
|
||||||
allow_multistar: false,
|
allow_multistar: false,
|
||||||
negative_emojis: [],
|
|
||||||
enabled: true,
|
enabled: true,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -41,6 +39,57 @@ export class StarboardPlugin extends ZeppelinPlugin<TConfigSchema> {
|
||||||
public static showInDocs = false;
|
public static showInDocs = false;
|
||||||
public static configSchema = ConfigSchema;
|
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 savedMessages: GuildSavedMessages;
|
||||||
protected starboardMessages: GuildStarboardMessages;
|
protected starboardMessages: GuildStarboardMessages;
|
||||||
|
|
||||||
|
@ -64,18 +113,32 @@ export class StarboardPlugin extends ZeppelinPlugin<TConfigSchema> {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
protected getStarboardOptsForSourceChannelId(sourceChannel): TStarboardOpts[] {
|
protected getStarboardOptsForSourceChannel(sourceChannel): TStarboardOpts[] {
|
||||||
const config = this.getConfigForChannel(sourceChannel);
|
const config = this.getConfigForChannel(sourceChannel);
|
||||||
return Object.values(config.entries)
|
|
||||||
.filter(opts => opts.source_channel_ids.includes(sourceChannel.id))
|
const configs = Object.values(config.entries).filter(opts => opts.source_channel_ids.includes(sourceChannel.id));
|
||||||
.map(opts => Object.assign({}, defaultStarboardOpts, opts));
|
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);
|
const config = this.getConfigForChannel(starboardChannel);
|
||||||
return Object.values(config.entries)
|
|
||||||
.filter(opts => opts.starboard_channel_id === starboardChannel.id)
|
const configs = Object.values(config.entries).filter(opts => opts.starboard_channel_id === starboardChannel.id);
|
||||||
.map(opts => Object.assign({}, defaultStarboardOpts, opts));
|
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() {
|
onLoad() {
|
||||||
|
@ -107,7 +170,7 @@ export class StarboardPlugin extends ZeppelinPlugin<TConfigSchema> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const applicableStarboards = await this.getStarboardOptsForSourceChannelId(msg.channel);
|
const applicableStarboards = await this.getStarboardOptsForSourceChannel(msg.channel);
|
||||||
|
|
||||||
for (const starboard of applicableStarboards) {
|
for (const starboard of applicableStarboards) {
|
||||||
// Instantly continue if the starboard is disabled
|
// Instantly continue if the starboard is disabled
|
||||||
|
@ -133,7 +196,6 @@ export class StarboardPlugin extends ZeppelinPlugin<TConfigSchema> {
|
||||||
*/
|
*/
|
||||||
async countReactions(msg: Message, counted: string[], countDouble: boolean) {
|
async countReactions(msg: Message, counted: string[], countDouble: boolean) {
|
||||||
let totalCount = [];
|
let totalCount = [];
|
||||||
countDouble = countDouble || false;
|
|
||||||
|
|
||||||
for (const emoji of counted) {
|
for (const emoji of counted) {
|
||||||
totalCount = await this.countReactionsForEmoji(msg, emoji, totalCount, countDouble);
|
totalCount = await this.countReactionsForEmoji(msg, emoji, totalCount, countDouble);
|
||||||
|
@ -243,7 +305,7 @@ export class StarboardPlugin extends ZeppelinPlugin<TConfigSchema> {
|
||||||
if (messages.length > 0) {
|
if (messages.length > 0) {
|
||||||
for (const starboardMessage of messages) {
|
for (const starboardMessage of messages) {
|
||||||
if (!starboardMessage.starboard_message_id) continue;
|
if (!starboardMessage.starboard_message_id) continue;
|
||||||
this.removeMessageFromStarboard(starboardMessage);
|
this.removeMessageFromStarboard(starboardMessage).catch(noop);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
messages = await this.starboardMessages.getStarboardMessagesForStarboardMessageId(msg.id);
|
messages = await this.starboardMessages.getStarboardMessagesForStarboardMessageId(msg.id);
|
||||||
|
@ -254,27 +316,36 @@ export class StarboardPlugin extends ZeppelinPlugin<TConfigSchema> {
|
||||||
this.removeMessageFromStarboardMessages(
|
this.removeMessageFromStarboardMessages(
|
||||||
starboardMessage.starboard_message_id,
|
starboardMessage.starboard_message_id,
|
||||||
starboardMessage.starboard_channel_id,
|
starboardMessage.starboard_channel_id,
|
||||||
);
|
).catch(noop);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@d.command("starboard migrate_pins", "<pinChannelId:channelId> <starboardChannelId:channelId>")
|
@d.command("starboard migrate_pins", "<pinChannelId:channelId> <starboardChannelId:channelId>", {
|
||||||
|
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 }) {
|
async migratePinsCmd(msg: Message, args: { pinChannelId: string; starboardChannelId }) {
|
||||||
try {
|
try {
|
||||||
const starboards = await this.getStarboardOptsForStarboardChannelId(this.bot.getChannel(args.starboardChannelId));
|
const starboards = await this.getStarboardOptsForStarboardChannel(this.bot.getChannel(args.starboardChannelId));
|
||||||
if (!starboards) {
|
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;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const channel = (await this.guild.channels.get(args.pinChannelId)) as GuildChannel & TextChannel;
|
const channel = (await this.guild.channels.get(args.pinChannelId)) as GuildChannel & TextChannel;
|
||||||
if (!channel) {
|
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;
|
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();
|
const pins = await channel.getPins();
|
||||||
pins.reverse(); // Migrate pins starting from the oldest message
|
pins.reverse(); // Migrate pins starting from the oldest message
|
||||||
|
@ -288,7 +359,7 @@ export class StarboardPlugin extends ZeppelinPlugin<TConfigSchema> {
|
||||||
await this.saveMessageToStarboard(pin, args.starboardChannelId);
|
await this.saveMessageToStarboard(pin, args.starboardChannelId);
|
||||||
}
|
}
|
||||||
|
|
||||||
msg.channel.createMessage(successMessage("Pins migrated!"));
|
msg.channel.createMessage(successMessage("Pins migrated!")).catch(noop);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
this.sendErrorMessage(
|
this.sendErrorMessage(
|
||||||
msg.channel,
|
msg.channel,
|
||||||
|
|
|
@ -189,7 +189,7 @@ const urlRegex = /(\S+\.\S+)/g;
|
||||||
const protocolRegex = /^[a-z]+:\/\//;
|
const protocolRegex = /^[a-z]+:\/\//;
|
||||||
|
|
||||||
export function getUrlsInString(str: string, unique = false): url.URL[] {
|
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));
|
if (unique) matches = Array.from(new Set(matches));
|
||||||
|
|
||||||
return matches.reduce((urls, match) => {
|
return matches.reduce((urls, match) => {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue