diff --git a/.gitignore b/.gitignore index 5b78a83..d6ea3ce 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,4 @@ node_modules json.sqlite +package-lock.json +package.json \ No newline at end of file diff --git a/.vscode/launch.json b/.vscode/launch.json new file mode 100644 index 0000000..ac44c31 --- /dev/null +++ b/.vscode/launch.json @@ -0,0 +1,17 @@ +{ + // Use IntelliSense to learn about possible attributes. + // Hover to view descriptions of existing attributes. + // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 + "version": "0.2.0", + "configurations": [ + { + "type": "node", + "request": "launch", + "name": "Launch Program", + "skipFiles": [ + "/**" + ], + "program": "${workspaceFolder}\\index.js" + } + ] +} \ No newline at end of file diff --git a/config.js b/config.js index c51c019..55b7897 100644 --- a/config.js +++ b/config.js @@ -1,7 +1,19 @@ module.exports = { - token: "YOUR_DISCORD_BOT_TOKEN", - channel: "XXXXXXXXXXXXXXXXXX", - messageTemplate: "Hello @everyone, **{author}** just now uploaded a video **{title}**!\n{url}", - channel_id: "YOUTUBE_CHANNEL_ID", - watchInterval: 30000 -} \ No newline at end of file + token: "your discord bot token", + messageTemplate: + "Hello everyone, **{author}** just now uploaded a video **{title}**!\n{url}", + //dont change messageTemplate + channel_id: [ + { + channel: "discord channel id 1", + youtube_channel_id: "advanced settings (in pc) -> youtube channel id", + }, + { + channel: "discord channel id 2", + youtube_channel_id: "youtube channel id 2", + }, + // ... more channels if you want same logic + ], + watchInterval: 10000, + youtubeApiKey: "Token from google cloud platform", +}; diff --git a/index.js b/index.js index de9c717..e2b7847 100644 --- a/index.js +++ b/index.js @@ -1,34 +1,52 @@ -const Discord = require("discord.js"); -const client = new Discord.Client(); -client.db = require("quick.db"); -client.request = new (require("rss-parser"))(); -client.config = require("./config.js"); - -client.on("ready", () => { - console.log("I'm ready!"); - handleUploads(); +const { Client, GatewayIntentBits } = require("discord.js"); +const axios = require("axios"); +const config = require("./config"); + +const client = new Client({ + intents: [GatewayIntentBits.Guilds, GatewayIntentBits.GuildMessages], }); -function handleUploads() { - if (client.db.fetch(`postedVideos`) === null) client.db.set(`postedVideos`, []); - setInterval(() => { - client.request.parseURL(`https://www.youtube.com/feeds/videos.xml?channel_id=${client.config.channel_id}`) - .then(data => { - if (client.db.fetch(`postedVideos`).includes(data.items[0].link)) return; - else { - client.db.set(`videoData`, data.items[0]); - client.db.push("postedVideos", data.items[0].link); - let parsed = client.db.fetch(`videoData`); - let channel = client.channels.cache.get(client.config.channel); - if (!channel) return; - let message = client.config.messageTemplate - .replace(/{author}/g, parsed.author) - .replace(/{title}/g, Discord.Util.escapeMarkdown(parsed.title)) - .replace(/{url}/g, parsed.link); - channel.send(message); - } - }); - }, client.config.watchInterval); +// Object to store last video IDs for each channel (avoiding global variable) +const lastVideoIds = {}; + +async function checkYouTube() { + try { + for (const channelConfig of config.channel_id) { + const { channel, youtube_channel_id } = channelConfig; + const lastVideoIdKey = `lastVideoId_${youtube_channel_id}`; + + const response = await axios.get( + `https://www.googleapis.com/youtube/v3/search?key=${config.youtubeApiKey}&channelId=${youtube_channel_id}&part=snippet,id&order=date&maxResults=1` + ); + + const video = response.data.items[0]; + + if ( + !lastVideoIds[lastVideoIdKey] || + video.id.videoId !== lastVideoIds[lastVideoIdKey] + ) { + lastVideoIds[lastVideoIdKey] = video.id.videoId; // Store last video ID for each channel + + const discordChannel = await client.channels.fetch(channel); + const message = config.messageTemplate + .replace("{author}", video.snippet.channelTitle) + .replace("{title}", video.snippet.title) + .replace( + "{url}", + `https://www.youtube.com/watch?v=${video.id.videoId}` + ); + discordChannel.send(message); + } + } + } catch (error) { + console.error("Error fetching YouTube data:", error); + } } -client.login(client.config.token); +client.once("ready", () => { + console.log("Bot is online!"); + checkYouTube(); + setInterval(checkYouTube, config.watchInterval); +}); + +client.login(config.token); diff --git a/package.json b/package.json index fde8d15..0a2e60b 100644 --- a/package.json +++ b/package.json @@ -4,26 +4,12 @@ "description": "Simple and easy to use discord bot to notify members whenever a video is posted on a YouTube channel.", "main": "index.js", "scripts": { - "test": "node index.js" + "test": "echo \"Error: no test specified\" && exit 1" }, - "repository": { - "type": "git", - "url": "git+https://github.com/Snowflake107/youtube-notification-bot.git" - }, - "keywords": [ - "youtube", - "discord.js", - "notification-bot" - ], - "author": "Snowflake07", - "license": "MIT", - "bugs": { - "url": "https://github.com/Snowflake07/youtube-notification-bot/issues" - }, - "homepage": "https://github.com/Snowflake07/youtube-notification-bot#readme", + "author": "", + "license": "ISC", "dependencies": { - "discord.js": "^12.0.2", - "quick.db": "^7.0.0-b22", - "rss-parser": "^3.7.5" + "axios": "^1.7.3", + "discord.js": "^14.15.3" } } diff --git a/readme.md b/readme.md index 52b0e8f..a1f748b 100644 --- a/readme.md +++ b/readme.md @@ -1,19 +1,122 @@ -# Youtube Notification Bot -Simple and easy to use discord bot to notify members whenever a video is posted on a YouTube channel. - -# Packages Used -- **[discord.js](https://npmjs.com/package/discord.js "View on npmjs")** -- **[quick.db](https://npmjs.com/package/quick.db "View on npmjs")** -- **[rss-parser](https://npmjs.com/package/rss-parser "View on npmjs")** - -# config.js - -```js -module.exports = { - token: "YOUR_DISCORD_BOT_TOKEN", // discord bot token - channel: "DISCORD_CHANNEL_ID", // channel id of a channel to send message - messageTemplate: "Hello @everyone, **{author}** just now uploaded a video **{title}**!\n{url}", // message to send on discord - channel_id: "YOUTUBE_CHANNEL_ID", // youtube channel id - watchInterval: 30000 // Check every 30 seconds -}; -``` +Absolutely! Here's the updated README with the changes incorporated: + +## Discord YouTube Notification Bot + +First, delete `package.json` if it exists, and run `npm init` to create a basic one. This bot checks your configured YouTube channels every **15 seconds** for new uploads or live streams and sends notifications to the corresponding Discord channels. It utilizes the YouTube Data API and the `discord.js` library. + +## Table of Contents + +- [Installation](#installation) +- [Configuration](#configuration) +- [Running the Bot](#running-the-bot) +- [Code Explanation](#code-explanation) +- [Dependencies](#dependencies) + +## Installation + +1. **Clone the Repository (if applicable):** + + ```bash + git clone https://github.com/your-username/discord-youtube-notification-bot.git + cd discord-youtube-notification-bot + ``` + +2. **Initialize `package.json`:** + + ```bash + npm init -y + ``` + + This creates a basic `package.json` file for your project. + +3. **Install Required Packages:** + + ```bash + npm install discord.js axios + ``` + +4. **Get YouTube Data API Key:** + + - Go to the [Google Cloud Console](https://console.cloud.google.com/). + - Create a new project (if needed). + - Enable the YouTube Data API v3 for your project. + - Create an API key. + +## Configuration + +1. **Create `config.js` File:** + + In the root directory of your project, create a file named `config.js` and add the following configuration: + + ```javascript + module.exports = { + token: "YOUR_DISCORD_BOT_TOKEN", + channel_id: [ + { + channel: "YOUR_DISCORD_CHANNEL_ID_1", + youtube_channel_id: "YOUR_YOUTUBE_CHANNEL_ID_1", + // optional: messageTemplate: "Custom template for channel 1" + }, + { + channel: "YOUR_DISCORD_CHANNEL_ID_2", + youtube_channel_id: "YOUR_YOUTUBE_CHANNEL_ID_2", + }, + // ... add more channel configurations + ], + watchInterval: 15000, // 15 seconds in milliseconds + youtubeApiKey: "YOUR_YOUTUBE_API_KEY", + }; + ``` + + - `token`: Your Discord bot token (from Developer Portal). + - `channel_id`: An array of objects containing configuration for each monitored channel. + - `channel`: ID of the Discord channel for notifications. + - `youtube_channel_id`: ID of the YouTube channel to monitor. + - `messageTemplate` (optional): Custom message template for this channel. + - `watchInterval`: The interval (in milliseconds) for checking new uploads (default: 15 seconds). + - `youtubeApiKey`: Your YouTube Data API key. + +## Running the Bot + +1. **Run the Bot:** + + ```bash + node index.js + ``` + + If everything is set up correctly, you should see the following output: + + ```bash + Bot is online! + ``` + +2. **Bot Operation:** + + - The bot checks for new uploads on your configured YouTube channels every 15 seconds. + - If a new video is found for any channel, it sends a notification to the corresponding Discord channel with a customized message template (if provided). + +## Code Explanation + +### `config.js` + +This file houses the configuration for your bot, including Discord bot token, channel configurations (with Discord and YouTube channel IDs, optional custom message templates), watch interval, and YouTube API key. + +### `index.js` + +This is the main file for the bot. It performs the following: + +- Initializes the Discord client. +- Iterates through each channel configuration in `config.js`. + - For each channel, fetches the latest video from the YouTube channel using the YouTube Data API. + - Compares the fetched video ID with the last fetched video ID stored separately for each channel (using a unique key). + - Sends a notification to the specified Discord channel if a new video is found, using the corresponding message template (if provided). + +### Key Functions: + +- `checkYouTube(config)`: Fetches the latest video from YouTube channels, compares IDs, and sends notifications if needed. +- `client.once('ready', ...)`: Runs when the bot is ready. Starts the initial check and sets up an interval for periodic checks. + +## Dependencies + +- **discord.js**: Library to interact with the Discord API. +- \*\*