Skip to content

Commit

Permalink
feat: add per manga configuration (channel, roles, threads...)
Browse files Browse the repository at this point in the history
  • Loading branch information
Coko7 committed Sep 15, 2022
1 parent cd936a9 commit 9e9911e
Show file tree
Hide file tree
Showing 6 changed files with 106 additions and 55 deletions.
5 changes: 3 additions & 2 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -89,5 +89,6 @@ lerna-debug.log
.DS_Store
Thumbs.db

# Ignore config file
config.json
# Ignore config file and data
config.json
data.json
64 changes: 42 additions & 22 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,37 +22,57 @@ npm i

## Configuration

Before running the bot for the first time, you need to modify its configuration in [config.json](config.json). Here is what the default configuration file looks like:

### Bot token and prefix
First, you need to create a Discord application and bot on Discord [Developer Portal](https://discord.com/developers/applications).
Then, create a file named `config.json` with the following content:
```json
{
"token": "YOUR_BOT_TOKEN",
"prefix": "!",
"opus": {
"scanSite": "https://onepiecechapters.com/",
"mangas": ["One Piece"],
"discord": {
"autoCreateThread": true,
"notifyRole": "YOUR_ROLE_ID",
"fromChannel": "YOUR_FROM_CHANNEL",
"toChannel": "YOUR_TO_CHANNEL"
}
}
}
```
Replace `YOUR_BOT_TOKEN` with the token of your bot.

Here is the list of keys you can set:
### OPUS setup

- token: The token of your discord bot
- opus:
- mangas: The names of the mangas you are interested in
- discord:
- autoCreateThread: Whether a new thread should be created for the released chapter. The thread will be attached to channel **toChannel**
- notifyRole: The ID of the role to notify once the chapter comes out
- fromChannel: The ID of the discord channel subscribed to the TCB server #releases channel
- toChannel:The ID of the discord channel where you want the final message to appear
Now that `config.json` has been created, you need to configure the bot to listen for specific manga releases and notify users.
To do that, open the file [opus-config.json](./opus-config.json). It should have the following content by default:

```json
{
"scanSite": "https://onepiecechapters.com/",
"mangas": [
{
"name": "One Piece",
"active": true,
"notifyRole": "DISCORD_ROLE_ID",
"fromChannel": "TCB_LISTEN_CHANNEL_ID",
"toChannel": "OPUS_NOTIFY_CHANNEL_ID",
"autoCreateThread": true
},
{
"name": "Black Clover",
"active": true,
"notifyRole": "DISCORD_ROLE_ID",
"fromChannel": "TCB_LISTEN_CHANNEL_ID",
"toChannel": "OPUS_NOTIFY_CHANNEL_ID",
"autoCreateThread": true
}
]
}
```

**NB:** Please do remember that your bot token must remain secret, do not share them with anyone unless you really trust them.
You do not need to change `scanSite` as only TCB can be used right now.
The default configuration registers listen events for two mangas: **One Piece** and **Black Clover**.
You can register as many mangas as you want as long as the scans exist on the TCB website.

Manga attributes:
- The `name` attribute of a manga is the most important as it is used to identify a manga on TCB. Make sure to get it right.
- The `active` attribute can be used to disable notification for a specific manga without removing its configuration.
- The `notifyRole` attribute will be used in the notification message to notify a specific Discord role. The value must be a valid Discord role ID on your Discord server. *This attribute is optional. If omitted, the notification message will not ping any role.*
- The `fromChannel` attribute is the Discord channel ID in which you receive TCB releases notifications.
- The `toChannel` attribute is the Discord channel ID of the channel where you want OPUS notifications to be sent.
- The `autoCreateThread` attribute is used to automatically create a thread to talk about a new chapter release. The thread will be attached to the `toChannel` channel. *This attribute is optional. If omitted, no thread will be created.*

## Launching the bot

Expand Down
14 changes: 0 additions & 14 deletions config.json

This file was deleted.

1 change: 0 additions & 1 deletion data.json

This file was deleted.

56 changes: 40 additions & 16 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,14 @@ const scraper = require("./scraper");

// Load config and data files
const config = require("./config.json");
const opus = require("./opus-config.json");
const data = require("./data.json");

// Load the manga interests and fix their case to be title case
const mangas = config.opus.mangas.map((m) => utils.toTitleCase(m));
const mangas = opus.mangas.map((m) => {
m.name = utils.toTitleCase(m.name);
return m;
});

client.once("ready", () => {
console.log("tcb-opus module is ready!");
Expand All @@ -24,33 +28,34 @@ client.on("messageCreate", async (message) => {
if (message.author.id === client.user.id) return;

// If the message was not sent in input channel, ignore it
if (message.channel.id !== config.opus.discord.fromChannel) return;
if (!isListenChannel(message.channel.id)) return;

// Check whether the message contains one of the desired mangas
const manga = mangas.find((m) =>
message.content.toLowerCase().includes(m.toLowerCase())
message.content.toLowerCase().includes(m.name.toLowerCase())
);

if (manga) {
if (manga && manga.active) {
// Fetch the latest chapter from TCBScans website
const res = await scraper.fetchLatestChapter(manga, config.opus.scanSite);
const res = await scraper.fetchLatestChapter(manga.name, opus.scanSite);

if (res.error) {
console.error(`Error occured while fetching ${manga}: ${res.error}`);
console.error(`Error occured while fetching ${manga.name}: ${res.error}`);
return;
} else if (res.chapter) {
// Find the output channel based on the channel Id in config
const channel = client.channels.cache.get(config.opus.discord.toChannel);
// Get the Discord output channel for the current manga
const channel = client.channels.cache.get(manga.toChannel);
const notifyPrefix = manga.notifyRole ? `<@&${manga.notifyRole}> ` : "";

// Send a message with the chapter link in the output channel
await channel.send(
`<@&${config.opus.discord.notifyRole}> ${manga} chapter **${res.chapter}** is out!\n${res.url}`
`${notifyPrefix}${manga.name} chapter **${res.chapter}** is out!\n${res.url}`
);

console.log(`Successfully fetched ${manga} chapter ${res.chapter}`);
console.log(`Successfully fetched ${manga.name} chapter ${res.chapter}`);

// Automatically create a thread to talk about the chapter if configured
if (config.opus.discord.autoCreateThread) {
if (manga.autoCreateThread) {
const threadName = `chap-${res.chapter}-talk`;

// Create thread if not exist
Expand All @@ -73,15 +78,17 @@ client.on("messageCreate", async (message) => {

// Update data file with latest chapter number
if (!data.mangas) data.mangas = [];
const stored = data.mangas.find((m) => m.name === manga);
const stored = data.mangas.find((m) => m.name === manga.name);

if (stored) {
// If the stored chapter is not the latest
if (stored.chapter < res.chapter) {
const missed = res.chapter - stored.chapter - 1;
if (missed > 0) {
console.log(
`I missed ${missed} ${manga} chapter${missed > 1 ? "s" : ""}!`
`I missed ${missed} ${manga.name} chapter${
missed > 1 ? "s" : ""
}!`
);
}

Expand All @@ -91,7 +98,7 @@ client.on("messageCreate", async (message) => {
}
} else {
data.mangas.push({
name: manga,
name: manga.name,
chapter: res.chapter,
url: res.url,
});
Expand All @@ -111,10 +118,11 @@ client.login(config.token);
* @access private
*
* @param {string} msg The discord message from TCB
* @param {string} manga The manga object
*
* @return {string} A formatted message containing the chapter link.
*/
function formatTCBMessage(msg) {
function formatTCBMessage(msg, manga) {
const urlStart = msg.indexOf("http");

if (urlStart === -1)
Expand All @@ -123,5 +131,21 @@ function formatTCBMessage(msg) {
const url = msg.slice(urlStart);
const chapNum = url.slice(url.lastIndexOf("-") + 1);

return `<@&${config.opus.discord.notifyRole}> One Piece chapter **${chapNum}** is out!\n${url}`;
return `<@&${manga.notifyRole}> ${manga.name} chapter **${chapNum}** is out!\n${url}`;
}

/**
* Fetch important elements from the TCB message and create a new message.
*
* @since 1.0.0
* @access private
*
* @param {string} channelId The ID of the discord channel where TCB updates are sent
*
* @return {bool} True if the channel is a TCB update channel, false otherwise.
*/
function isListenChannel(channelId) {
if (mangas.find((m) => m.fromChannel === channelId)) return true;

return false;
}
21 changes: 21 additions & 0 deletions opus-config.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
{
"scanSite": "https://onepiecechapters.com/",
"mangas": [
{
"name": "One Piece",
"active": true,
"notifyRole": "DISCORD_ROLE_ID",
"fromChannel": "TCB_LISTEN_CHANNEL_ID",
"toChannel": "OPUS_NOTIFY_CHANNEL_ID",
"autoCreateThread": true
},
{
"name": "Black Clover",
"active": true,
"notifyRole": "DISCORD_ROLE_ID",
"fromChannel": "TCB_LISTEN_CHANNEL_ID",
"toChannel": "OPUS_NOTIFY_CHANNEL_ID",
"autoCreateThread": true
}
]
}

0 comments on commit 9e9911e

Please sign in to comment.