Skip to content

Commit ecdbadf

Browse files
authored
Merge pull request #1 from GalvinPython/main
update dev branch
2 parents 96a7ec9 + ce01b8d commit ecdbadf

File tree

7 files changed

+52
-33
lines changed

7 files changed

+52
-33
lines changed

README.md

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,3 +27,13 @@ Feedr strives for constant improvement, so here's what will be implemented
2727
* Embed Links
2828
* Attach Files
2929
* Add Reactions
30+
31+
# Changelog
32+
## 1.1.0
33+
* Replies are no longer deferred
34+
* Messages can now be sent in Announcement channels [1.0.3]
35+
* Better checking for valid YouTube channel IDs
36+
* Channels with no uploads will be tracked now
37+
38+
## 1.0.0
39+
* Initial release

package-lock.json

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
"name": "videonotifier",
33
"module": "src/index.ts",
44
"type": "module",
5-
"version": "1.0.0",
5+
"version": "1.1.0",
66
"devDependencies": {
77
"@types/bun": "1.1.6"
88
},

src/commands.ts

Lines changed: 31 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -148,10 +148,14 @@ const commands: Record<string, Command> = {
148148
const discordChannelId = interaction.options.get('updates_channel')?.value as string;
149149
const guildId = interaction.guildId;
150150

151-
// Deferring the reply is not the best practice,
152-
// but in case the network/database is slow, it's better to defer the reply
153-
// so we don't get a timeout error
154-
await interaction.deferReply();
151+
// Check that the channel ID is in a valid format
152+
if (youtubeChannelId.length != 24 || !youtubeChannelId.startsWith('UC')) {
153+
await interaction.reply({
154+
ephemeral: true,
155+
content: 'Invalid YouTube channel ID format!',
156+
});
157+
return;
158+
}
155159

156160
// DMs are currently not supported, so throw back an error
157161
if (!guildId || interaction.channel?.isDMBased()) {
@@ -173,24 +177,28 @@ const commands: Record<string, Command> = {
173177

174178
// Check if the bot has the required permissions for the target channel
175179
const targetChannel = await client.channels.fetch(discordChannelId);
176-
if (targetChannel && targetChannel.type === ChannelType.GuildText) {
180+
if (targetChannel && (targetChannel.type === ChannelType.GuildText || targetChannel.type === ChannelType.GuildAnnouncement)) {
181+
const requiredPermissions = [
182+
{ flag: PermissionFlagsBits.ViewChannel, name: 'View Channel' },
183+
{ flag: PermissionFlagsBits.SendMessages, name: 'Send Messages' },
184+
{ flag: PermissionFlagsBits.SendMessagesInThreads, name: 'Send Messages in Threads' },
185+
{ flag: PermissionFlagsBits.EmbedLinks, name: 'Embed Links' },
186+
{ flag: PermissionFlagsBits.AttachFiles, name: 'Attach Files' },
187+
{ flag: PermissionFlagsBits.AddReactions, name: 'Add Reactions' }
188+
];
177189
const botPermissions = targetChannel.permissionsFor(client.user?.id as unknown as GuildMember);
178-
if (
179-
!botPermissions?.has(PermissionFlagsBits.ViewChannel) ||
180-
!botPermissions?.has(PermissionFlagsBits.SendMessages) ||
181-
!botPermissions?.has(PermissionFlagsBits.SendMessagesInThreads) ||
182-
!botPermissions?.has(PermissionFlagsBits.EmbedLinks) ||
183-
!botPermissions?.has(PermissionFlagsBits.AttachFiles) ||
184-
!botPermissions?.has(PermissionFlagsBits.AddReactions)
185-
) {
186-
await interaction.followUp({
190+
const missingPermissions = requiredPermissions
191+
.filter(permission => !botPermissions?.has(permission.flag))
192+
.map(permission => permission.name);
193+
if (missingPermissions.length > 0) {
194+
await interaction.reply({
187195
ephemeral: true,
188-
content: 'The bot does not have the required permissions for the target channel!',
196+
content: `The bot does not have the required permissions for the target channel! Missing permissions: ${missingPermissions.join(', ')}`,
189197
});
190198
return;
191199
}
192200
} else {
193-
await interaction.followUp({
201+
await interaction.reply({
194202
ephemeral: true,
195203
content: 'The target channel is not a text channel!',
196204
});
@@ -199,16 +207,16 @@ const commands: Record<string, Command> = {
199207

200208
// Check if the channel is valid
201209
if (!await checkIfChannelIdIsValid(youtubeChannelId)) {
202-
await interaction.followUp({
210+
await interaction.reply({
203211
ephemeral: true,
204-
content: 'Invalid YouTube channel ID!',
212+
content: 'That channel doesn\'t exist!',
205213
});
206214
return;
207215
}
208216

209217
// Check if the channel is already being tracked in the guild
210218
if (await checkIfGuildIsTrackingChannelAlready(youtubeChannelId, guildId)) {
211-
await interaction.followUp({
219+
await interaction.reply({
212220
ephemeral: true,
213221
content: 'This channel is already being tracked!',
214222
});
@@ -218,7 +226,7 @@ const commands: Record<string, Command> = {
218226
// Check if the channel is already being tracked globally
219227
if (!await checkIfChannelIsAlreadyTracked(youtubeChannelId)) {
220228
if (!await addNewChannelToTrack(youtubeChannelId)) {
221-
await interaction.followUp({
229+
await interaction.reply({
222230
ephemeral: true,
223231
content: 'An error occurred while trying to add the channel to track! This is a new channel being tracked globally, please report this error!',
224232
});
@@ -229,15 +237,15 @@ const commands: Record<string, Command> = {
229237
// Add the guild to the database
230238
if (await addNewGuildToTrackChannel(guildId, youtubeChannelId, discordChannelId, interaction.options.get('role')?.value as string ?? null)) {
231239
const channelIdInfo = await client.channels.fetch(discordChannelId);
232-
if (channelIdInfo && channelIdInfo.type === ChannelType.GuildText) {
240+
if (channelIdInfo && (channelIdInfo.type === ChannelType.GuildText || channelIdInfo.type === ChannelType.GuildAnnouncement)) {
233241
const youtubeChannelInfo = await getChannelDetails(youtubeChannelId)
234242

235-
await interaction.followUp({
243+
await interaction.reply({
236244
ephemeral: true,
237245
content: `Started tracking the channel ${youtubeChannelInfo?.channelName ?? youtubeChannelId} in ${channelIdInfo.name}!`,
238246
});
239247
} else {
240-
await interaction.followUp({
248+
await interaction.reply({
241249
ephemeral: true,
242250
content: 'The channel to send updates to is not a text channel! Please make sure to set a text channel!',
243251
});

src/database.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ export async function initTables(): Promise<boolean> {
1414
const createYouTubeTable = `
1515
CREATE TABLE IF NOT EXISTS youtube (
1616
youtube_channel_id VARCHAR(255) NOT NULL PRIMARY KEY,
17-
latest_video_id VARCHAR(255) NOT NULL UNIQUE
17+
latest_video_id VARCHAR(255) UNIQUE
1818
);
1919
`;
2020
const createDiscordTable = `
@@ -71,7 +71,7 @@ export async function addNewChannelToTrack(channelId: string) {
7171
}
7272

7373
const data = await res.json();
74-
const videoId = data.items[0].snippet.thumbnails.default.url.split('/')[4];
74+
const videoId = data.items?.[0]?.snippet?.thumbnails?.default?.url?.split('/')[4] || null;
7575

7676
const query = `INSERT INTO youtube (youtube_channel_id, latest_video_id) VALUES (?, ?)`;
7777
return new Promise<boolean>((resolve, reject) =>
Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import { env } from "../config"
22

33
export default async function checkIfChannelIdIsValid(channelId: string) {
4-
const res = await fetch(`https://www.googleapis.com/youtube/v3/channels?part=snippet&id=${channelId}&key=${env.youtubeApiKey}`)
5-
return res.ok
4+
const res = await fetch(`https://www.googleapis.com/youtube/v3/channels?part=snippet&id=${channelId}&key=${env.youtubeApiKey}`);
5+
const data = await res.json();
6+
return data.items !== undefined && data.items.length > 0;
67
}

src/utils/fetchLatestUploads.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -63,10 +63,10 @@ export default async function fetchLatestUploads() {
6363
}
6464

6565
await (channelObj as TextChannel).send({
66-
content: guild.guild_ping_role && channelInfo ? `<@&${guild.guild_ping_role}> New video uploaded for ${channelInfo?.channelName}! https://www.youtube.com/watch?v=${videoId}` :
66+
content: guild.guild_ping_role && channelInfo ? `<@&${guild.guild_ping_role}> New video uploaded for ${channelInfo?.channelName}! https://www.youtube.com/watch?v=${videoId}` :
6767
guild.guild_ping_role ? `<@&${guild.guild_ping_role}> New video uploaded! https://www.youtube.com/watch?v=${videoId}` :
68-
channelInfo ? `New video uploaded for ${channelInfo.channelName}! https://www.youtube.com/watch?v=${videoId}` :
69-
`New video uploaded! https://www.youtube.com/watch?v=${videoId}`
68+
channelInfo ? `New video uploaded for ${channelInfo.channelName}! https://www.youtube.com/watch?v=${videoId}` :
69+
`New video uploaded! https://www.youtube.com/watch?v=${videoId}`
7070
});
7171
} catch (error) {
7272
console.error("Error fetching or sending message to channel in fetchLatestUploads:", error);

0 commit comments

Comments
 (0)