Skip to content

Commit

Permalink
feat: Added %link% and per-streamer message.
Browse files Browse the repository at this point in the history
  • Loading branch information
KararTY committed Jul 13, 2021
1 parent 353630d commit 603fcf2
Show file tree
Hide file tree
Showing 6 changed files with 1,705 additions and 1,629 deletions.
15 changes: 12 additions & 3 deletions README.md
@@ -1,17 +1,21 @@
# DiscordTwitchAnnouncer
## Announces when Twitch channels go live, in Discord.

## Announces when Twitch channels go live, in Discord

### Updating from 2.x to 3.x

1. Update your NodeJS version to 12.16.3 or a later version! **(Tested on 12.16.3 and 14.1.0)**
2. Please run `npm install` again to update libraries and dependencies!
3. Please add `twitch.clientSecret` to `settings.js` file.
4. **Please do not share** your `settings.js` file and the new `token.json` file. They both include secrets that allow other people to use your authentications.

### 5 Step Setup.
### 5 Step Setup

1. Get NodeJS, v12.x.x or newer **(Tested & Works on v12.16.3)**.
2. Git clone or download this repository and then change to the directory in your console/terminal.
3. Type `npm install` in your console/terminal and wait for dependencies to download and install successfully.
4. Open up `settings.js` with any text program:

```js
module.exports = {
timer: 61000, // Is in milliseconds. Default: 61000 ms = 1 minute & 1 second.
Expand All @@ -35,14 +39,17 @@ module.exports = {
}
}
```

5. Change the fields accordingly. *(Fields `twitch.clientID`, `twitch.clientSecret` & `discord.token` must have a value, otherwise program will error.)*

**Type `node app.js` in your console/terminal to run program.**

After you've started the announcer, invite the bot and go to your discord channel.

#### Commands

Available commands:

* `!help`
* `!uptime`
* (Example) `!timezone sv-SE Europe/Stockholm` Check [IANA BCP 47 Subtag registry](https://www.iana.org/assignments/language-subtag-registry/language-subtag-registry) & [IETF RFC 5646](https://tools.ietf.org/html/rfc5646) for locale tags and [IANA Time Zone Database](https://www.iana.org/time-zones) or [Wikipedia](https://en.wikipedia.org/wiki/List_of_tz_database_time_zones) for timezones.
Expand All @@ -52,16 +59,18 @@ Available commands:
* (Example) `!add Streamer_Name`
* (Example) `!remove Streamer_Name`
* (Example) `!reaction 👍`
* (Example) `!message @here %name% is **%status%** streaming, **%game%**: *%title%*`
* (Example) `!message <streamerName> @here %name% is **%status%** streaming, **%game%**: *%title%* %link%`
* `%name%` Streamer's name
* `%status%` VOD / LIVE / RERUN?
* `%game%` Game name
* `%title%` Stream title
* `%link%` Twitch link
* (Example) `!prefix #`
* (Example) `!language english` Check i18n folder for available languages.
* (Example) `!announcementchannel Streamer_Name 000000000000000000`

### Contributing

Fork project & Send a pull request. Use eslint, thanks.

### License MIT
68 changes: 61 additions & 7 deletions app.js
Expand Up @@ -176,6 +176,31 @@ async function refreshAppToken () {
return true
}

async function sendTestMessage (translate, message, streamer = 'twitchdev') {
const test = {
gameInfo: {
name: translate.commands.add.gameInfoName,
box_art_url: 'https://static-cdn.jtvnw.net/ttv-boxart/Science%20&%20Technology-{width}x{height}.jpg'
},
streamInfo: {
name: streamer,
avatar: 'https://brand.twitch.tv/assets/images/twitch-extruded.png',
type: translate.commands.add.streamInfoType,
title: translate.commands.add.streamInfoTitle
}
}

try {
const embed = streamPreviewEmbed(message.gid, { ...test, imageFileName: null })
embed.setImage('https://static-cdn.jtvnw.net/ttv-static/404_preview-1920x1080.jpg')
await message.discord.channel.send(parseAnnouncementMessage(message.gid, test), { embed })
} catch (err) {
if (err.message !== 'Missing Permissions') {
await message.discord.channel.send(parseAnnouncementMessage(message.gid, test))
}
}
}

class Message {
constructor (message) {
this.cmd = message.content.replace(new RegExp(`^<@${client.user.id}> `), '!').split(/[ ]+/)
Expand Down Expand Up @@ -388,13 +413,26 @@ const commands = (translate) => [
.replace('%1', translate.example)
.replace('%2', message.prefix)
},
handler: (message) => {
handler: async (message) => {
// Change stream announcement message.
const cleanedContent = message.cmd.slice(1).join(' ')
if (cleanedContent.length > 0) {
if (cleanedContent.length === 0) return false

const streamersIndex = data.guilds[message.gid].streamers.findIndex(i => i.name === message.cmd[1].toLowerCase())
// Change announcement message for said streamer.
if (streamersIndex > -1) {
data.guilds[message.gid].streamers[streamersIndex].message = message.cmd.slice(2).join(' ')
saveData([{ guild: message.gid, entry: 'streamers', value: data.guilds[message.gid].streamers }])

await sendTestMessage(translate, message, message.cmd[1])
return message.discord.reply(translate.commands.message.messageStreamer
.replace('%1', message.cmd[1]))
} else {
saveData([{ guild: message.gid, entry: 'message', value: cleanedContent }])

await sendTestMessage(translate, message)
return message.discord.reply(translate.commands.message.message)
} else return false
}
}
}),
new Command({
Expand Down Expand Up @@ -559,7 +597,14 @@ async function check () {
}
}

const streamedGames = await Promise.all(promise)
let streamedGames

try {
streamedGames = await Promise.all(promise)
} catch (error) {
console.error(error)
}

const announcements = []
for (let index = 0; index < guildIDs.length; index++) {
const guildID = guildIDs[index]
Expand All @@ -570,6 +615,7 @@ async function check () {
const isStreaming = cache[guildID][i].streaming
const started = streams.find(s => s.name.toLowerCase() === cache[guildID][i].name.toLowerCase()).started
const lastStartedAt = data.guilds[guildID].streamers.find(s => s.name.toLowerCase() === cache[guildID][i].name.toLowerCase()).lastStartedAt

if (!isStreaming && new Date(started).getTime() > new Date(lastStartedAt || 0).getTime()) {
// Push info.
const streamInfo = streams.find(s => s.name.toLowerCase() === cache[guildID][i].name.toLowerCase())
Expand Down Expand Up @@ -622,11 +668,17 @@ const streamPreviewEmbed = (guildID, { imageFileName, streamInfo, gameInfo }) =>
}

const parseAnnouncementMessage = (guildID, { streamInfo, gameInfo }) => {
return data.guilds[guildID].message
const streamer = data.guilds[guildID].streamers.find(s => s.name === streamInfo.name.toLowerCase())
let message = (streamer && streamer.message && streamer.message.length > 0) ? streamer.message : data.guilds[guildID].message

if (!message.includes('%link%')) message += ` http://www.twitch.tv/${streamInfo.name}`

return message
.replace('%name%', streamInfo.name)
.replace('%status%', streamInfo.type.toUpperCase())
.replace('%game%', gameInfo ? gameInfo.name : translate.unknownGame)
.replace('%title%', streamInfo.title)
.replace('%link%', `http://www.twitch.tv/${streamInfo.name}`)
}

async function sendMessage (guildID, streamerInfo, { cachedImage, streamInfo, gameInfo }) {
Expand All @@ -639,12 +691,12 @@ async function sendMessage (guildID, streamerInfo, { cachedImage, streamInfo, ga
let message
const parsedAnnouncementMessage = parseAnnouncementMessage(guildID, { streamInfo, gameInfo })
try {
message = await client.channels.cache.get(announcementChannel).send(`${parsedAnnouncementMessage} http://www.twitch.tv/${streamInfo.name}`, {
message = await client.channels.cache.get(announcementChannel).send(parsedAnnouncementMessage, {
embed, files: [{ attachment: cachedImage, name: imageFileName }]
})
} catch (err) {
if (err.message === 'Missing Permissions') {
message = await client.channels.cache.get(announcementChannel).send(`${parsedAnnouncementMessage} http://www.twitch.tv/${streamInfo.name}`)
message = await client.channels.cache.get(announcementChannel).send(parsedAnnouncementMessage)
} else console.error(err.name, err.message, err.code, translate.inGuild.concat(client.guilds.cache.get(guildID).name))
}

Expand All @@ -668,6 +720,7 @@ async function sendMessage (guildID, streamerInfo, { cachedImage, streamInfo, ga

client.on('message', message => {
let allow = false

if (message.guild && message.member) {
// If message comes from a guild and guild member.
if (data.guilds[message.guild.id].operator && data.guilds[message.guild.id].operator.length > 0) {
Expand All @@ -687,6 +740,7 @@ client.on('message', message => {
allow = true
}
}

if (allow) {
const cleanedMessage = message.content.replace(new RegExp(`^<@${client.user.id}> `), '!')
if (message.cleanContent.startsWith(data.guilds[message.guild.id].prefix || '!') || message.mentions.users.find(u => u.id === client.user.id)) {
Expand Down
5 changes: 3 additions & 2 deletions i18n/english.json
Expand Up @@ -82,8 +82,9 @@
},
"message": {
"triggers": ["msg", "message"],
"helpText": "%1 `%2message @everyone %name% **%status%**, with **%game%**: *%title%*` (Change stream announcement message. Supports *%name%* for streamer's name, *%status%* for type of stream (VOD, LIVE, RERUN), *%game%* for game title and *%title%* for stream title.)",
"message": "Changed announcement message."
"helpText": "%1 `%2message <streamerName> @everyone %name% **%status%**, with **%game%**: *%title%*` (Change stream announcement message. If *<streamerName>* is filled out, it will change that streamer's announcement message. Make sure to remove the `<>`. Supports *%name%* for streamer's name, *%status%* for type of stream (VOD, LIVE, RERUN), *%game%* for game title and *%title%* for stream title, *%link%* for twitch link.)",
"message": "Changed announcement message.",
"messageStreamer": "Changed announcement message for streamer %1."
},
"prefix": {
"triggers": ["pfx", "prefix"],
Expand Down

0 comments on commit 603fcf2

Please sign in to comment.