Merge pull request #27 from keanuplayz/feature/stream-events

This commit is contained in:
Keanu Timmermans 2021-04-06 16:10:21 +02:00 committed by GitHub
commit 4978aceec6
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 153 additions and 0 deletions

View File

@ -164,6 +164,47 @@ export default new Command({
})
})
}
}),
stream: new Command({
description: "Set a channel to send stream notifications. Type `#` to reference the channel.",
usage: "(<channel mention>)",
async run($) {
if ($.guild) {
const guild = Storage.getGuild($.guild.id);
if (guild.streamingChannel) {
guild.streamingChannel = null;
$.channel.send("Removed your server's stream notifications channel.");
} else {
guild.streamingChannel = $.channel.id;
$.channel.send(`Set your server's stream notifications channel to ${$.channel}.`);
}
Storage.save();
} else {
$.channel.send("You must use this command in a server.");
}
},
// If/when channel types come out, this will be the perfect candidate to test it.
any: new Command({
async run($) {
if ($.guild) {
const match = $.args[0].match(/^<#(\d{17,19})>$/);
if (match) {
Storage.getGuild($.guild.id).streamingChannel = match[1];
Storage.save();
$.channel.send(`Successfully set this server's welcome channel to ${match[0]}.`);
} else {
$.channel.send(
"You must provide a reference channel. You can do this by typing `#` then searching for the proper channel."
);
}
} else {
$.channel.send("You must use this command in a server.");
}
}
})
})
}
}),

View File

@ -0,0 +1,18 @@
import Command from "../../core/command";
import {streamList} from "../../events/voiceStateUpdate";
export default new Command({
description: "Sets the description of your stream. You can embed links by writing `[some name](some link)`",
async run($) {
const userID = $.author.id;
if (streamList.has(userID)) {
const stream = streamList.get(userID)!;
stream.description = $.args.join(" ") || "No description set.";
stream.update();
} else {
// Alternatively, I could make descriptions last outside of just one stream.
$.channel.send("You can only use this command when streaming.");
}
}
});

View File

@ -58,11 +58,13 @@ class Guild {
public welcomeType: "none" | "text" | "graphical";
public welcomeChannel: string | null;
public welcomeMessage: string | null;
public streamingChannel: string | null;
constructor(data?: GenericJSON) {
this.prefix = select(data?.prefix, null, String);
this.welcomeChannel = select(data?.welcomeChannel, null, String);
this.welcomeMessage = select(data?.welcomeMessage, null, String);
this.streamingChannel = select(data?.streamingChannel, null, String);
switch (data?.welcomeType) {
case "text":

View File

@ -0,0 +1,14 @@
import Event from "../core/event";
import {streamList} from "./voiceStateUpdate";
export default new Event<"channelUpdate">({
async on(before, after) {
if (before.type === "voice" && after.type === "voice") {
for (const stream of streamList.values()) {
if (after.id === stream.channel.id) {
stream.update();
}
}
}
}
});

View File

@ -0,0 +1,78 @@
import {GuildMember, VoiceChannel, MessageEmbed, TextChannel, Permissions, Message, Collection} from "discord.js";
import Event from "../core/event";
import $ from "../core/lib";
import {Storage} from "../core/structures";
import {client} from "../index";
type Stream = {
streamer: GuildMember;
channel: VoiceChannel;
description?: string;
message: Message;
update: () => void;
};
// A list of user IDs and message embeds.
export const streamList = new Collection<string, Stream>();
// Probably find a better, DRY way of doing this.
function getStreamEmbed(streamer: GuildMember, channel: VoiceChannel, description?: string): MessageEmbed {
const user = streamer.user;
const embed = new MessageEmbed()
.setTitle(`Stream: \`#${channel.name}\``)
.setAuthor(
streamer.nickname ?? user.username,
user.avatarURL({
dynamic: true,
format: "png"
}) ?? user.defaultAvatarURL
)
.setColor(streamer.displayColor);
if (description) {
embed.setDescription(description);
}
return embed;
}
export default new Event<"voiceStateUpdate">({
async on(before, after) {
const isStartStreamEvent = !before.streaming && after.streaming;
const isStopStreamEvent = before.streaming && (!after.streaming || !after.channel); // If you were streaming before but now are either not streaming or have left the channel.
// Note: isStopStreamEvent can be called twice in a row - If Discord crashes/quits while you're streaming, it'll call once with a null channel and a second time with a channel.
if (isStartStreamEvent || isStopStreamEvent) {
const {streamingChannel} = Storage.getGuild(after.guild.id);
if (streamingChannel) {
const member = after.member!;
const voiceChannel = after.channel!;
const textChannel = client.channels.cache.get(streamingChannel);
if (textChannel instanceof TextChannel) {
if (isStartStreamEvent) {
streamList.set(member.id, {
streamer: member,
channel: voiceChannel,
message: await textChannel.send(getStreamEmbed(member, voiceChannel)),
update(this: Stream) {
this.message.edit(getStreamEmbed(this.streamer, this.channel, this.description));
}
});
} else if (isStopStreamEvent) {
if (streamList.has(member.id)) {
const {message} = streamList.get(member.id)!;
message.delete();
streamList.delete(member.id);
}
}
} else {
$.error(
`The streaming notifications channel ${streamingChannel} for guild ${after.guild.id} either doesn't exist or isn't a text channel.`
);
}
}
}
}
});