From 9050e4b6ed8c2e8a081f1ab8e75efc3d74ca87ac Mon Sep 17 00:00:00 2001 From: Talon Date: Mon, 5 Apr 2021 15:50:51 +0200 Subject: [PATCH] Add code --- .DS_Store | Bin 0 -> 6148 bytes index.js | 92 +++++++++++++++++++++++++++ package-lock.json | 157 ++++++++++++++++++++++++++++++++++++++++++++++ package.json | 20 ++++++ voice-test.js | 19 ++++++ 5 files changed, 288 insertions(+) create mode 100644 .DS_Store create mode 100644 index.js create mode 100644 package-lock.json create mode 100644 package.json create mode 100644 voice-test.js diff --git a/.DS_Store b/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..c435fb72c20b2f4824116a18c943e9c642078df7 GIT binary patch literal 6148 zcmeHK!A`?447FiM1%$LC$DFzC55iQwpdSEiLon1X6@s1nZ~OsY#B*$VdeVkpqUzhWBX|<lV~d3EFu*_}8ldhZN417ik`bvTv#{|3KI zvB)2X_{bS>2L2cWJgJ*{j*qgt_1ovkT^rEu&_u*<5CsB#^a#K}&XLPJsq;Z}_(j7( VQL>0VhXef~kO}e58TbJPJ^@AWHL?Hz literal 0 HcmV?d00001 diff --git a/index.js b/index.js new file mode 100644 index 0000000..9d8694c --- /dev/null +++ b/index.js @@ -0,0 +1,92 @@ +const Discord = require('discord.js'); +require('dotenv').config(); +const tts = require('google-tts-api'); +const fetch = require('node-fetch'); +const fs = require('fs'); +const sha1 = require('sha1'); + +let joinedVoiceChannels = []; + +const bot = new Discord.Client(); + +bot.on('message', (message) => { + console.log("I got a message", message); +}) + +bot.on('ready', async () => { + console.log("Bot initialized and listening"); + const guild = await bot.guilds.fetch(process.env.GUILD); + const channel = await bot.channels.fetch(process.env.CHANNEL); + await joinChannel(channel); + + speak(channel, `Hi! I'm alive. It is now ${new Date().toLocaleTimeString()} on ${new Date().toLocaleDateString()}`); +}) + +bot.on('voiceStateUpdate', async (oldState, newState) => { + if (newState.member.user.bot) return; + if (oldState.channel && newState.channel) return; + const channel = oldState.channel || newState.channel; + if (!channel) return; + if (channel.members.array().length < 2) { + return await leaveChannel(channel); + } + await joinChannel(channel); + let joined = false; + if (!oldState.channel) { + joined = true; + } + + let username = newState.member.displayName; + let str = ""; + if (!joined) { + str = username + " left the channel"; + } else { + str = username + " joined the channel"; + } + speak(channel, str); +}) + + +bot.login(process.env.TOKEN); + +function isInVoiceChannel(channel) { + return joinedVoiceChannels.includes(channel); +} + +function getConnectionForVoiceChannel(channel) { + return bot.voice.connections.find((conn) => conn.channel === channel); +} + +async function generateVoice(string) { + const hash = sha1(string); + const filepath = process.env.VOICE_TMP_PATH + hash + ".mp3"; + if (!fs.existsSync(filepath)) { + const url = tts.getAudioUrl(string, {lang: "en-us"}); + console.log("Generated url: " + url); + const data = await fetch(url); + const contents = await data.arrayBuffer(); + const buf = Buffer.from(contents); + fs.writeFileSync(filepath, buf); + } + return filepath; +} + +async function joinChannel(channel) { + if (!isInVoiceChannel(channel)) { + const res = await channel.join(); + joinedVoiceChannels.push(channel); + } +} + +async function leaveChannel(channel) { + if (joinedVoiceChannels.includes(channel)) { + joinedVoiceChannels = joinedVoiceChannels.filter((chan) => chan !== channel); + await channel.leave(); + } +} + +async function speak(channel, message) { + const conn = getConnectionForVoiceChannel(channel); + const filepath = await generateVoice(message); + if (conn) conn.play(filepath); +} diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 0000000..d4a2b2d --- /dev/null +++ b/package-lock.json @@ -0,0 +1,157 @@ +{ + "name": "tardis-bot", + "version": "1.0.0", + "lockfileVersion": 1, + "requires": true, + "dependencies": { + "@discordjs/collection": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/@discordjs/collection/-/collection-0.1.6.tgz", + "integrity": "sha512-utRNxnd9kSS2qhyivo9lMlt5qgAUasH2gb7BEOn6p0efFh24gjGomHzWKMAPn2hEReOPQZCJaRKoURwRotKucQ==" + }, + "@discordjs/form-data": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@discordjs/form-data/-/form-data-3.0.1.tgz", + "integrity": "sha512-ZfFsbgEXW71Rw/6EtBdrP5VxBJy4dthyC0tpQKGKmYFImlmmrykO14Za+BiIVduwjte0jXEBlhSKf0MWbFp9Eg==", + "requires": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "mime-types": "^2.1.12" + } + }, + "abort-controller": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/abort-controller/-/abort-controller-3.0.0.tgz", + "integrity": "sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==", + "requires": { + "event-target-shim": "^5.0.0" + } + }, + "asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=" + }, + "axios": { + "version": "0.21.1", + "resolved": "https://registry.npmjs.org/axios/-/axios-0.21.1.tgz", + "integrity": "sha512-dKQiRHxGD9PPRIUNIWvZhPTPpl1rf/OxTYKsqKUDjBwYylTvV7SjSHJb9ratfyzM6wCdLCOYLzs73qpg5c4iGA==", + "requires": { + "follow-redirects": "^1.10.0" + } + }, + "charenc": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/charenc/-/charenc-0.0.2.tgz", + "integrity": "sha1-wKHS86cJLgN3S/qD8UwPxXkKhmc=" + }, + "combined-stream": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", + "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "requires": { + "delayed-stream": "~1.0.0" + } + }, + "crypt": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/crypt/-/crypt-0.0.2.tgz", + "integrity": "sha1-iNf/fsDfuG9xPch7u0LQRNPmxBs=" + }, + "delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=" + }, + "discord.js": { + "version": "12.5.3", + "resolved": "https://registry.npmjs.org/discord.js/-/discord.js-12.5.3.tgz", + "integrity": "sha512-D3nkOa/pCkNyn6jLZnAiJApw2N9XrIsXUAdThf01i7yrEuqUmDGc7/CexVWwEcgbQR97XQ+mcnqJpmJ/92B4Aw==", + "requires": { + "@discordjs/collection": "^0.1.6", + "@discordjs/form-data": "^3.0.1", + "abort-controller": "^3.0.0", + "node-fetch": "^2.6.1", + "prism-media": "^1.2.9", + "setimmediate": "^1.0.5", + "tweetnacl": "^1.0.3", + "ws": "^7.4.4" + } + }, + "dotenv": { + "version": "8.2.0", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-8.2.0.tgz", + "integrity": "sha512-8sJ78ElpbDJBHNeBzUbUVLsqKdccaa/BXF1uPTw3GrvQTBgrQrtObr2mUrE38vzYd8cEv+m/JBfDLioYcfXoaw==" + }, + "event-target-shim": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/event-target-shim/-/event-target-shim-5.0.1.tgz", + "integrity": "sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ==" + }, + "follow-redirects": { + "version": "1.13.3", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.13.3.tgz", + "integrity": "sha512-DUgl6+HDzB0iEptNQEXLx/KhTmDb8tZUHSeLqpnjpknR70H0nC2t9N73BK6fN4hOvJ84pKlIQVQ4k5FFlBedKA==" + }, + "google-tts-api": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/google-tts-api/-/google-tts-api-2.0.2.tgz", + "integrity": "sha512-MkQYbBJEdom8hJpfEVDfD3tpBtkz0X59C+FNsoRhbnCiFjZRnzyurGQ5OrAr3xkigII56/jmk0JNwZsp450G+Q==", + "requires": { + "axios": "^0.21.0" + } + }, + "mime-db": { + "version": "1.47.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.47.0.tgz", + "integrity": "sha512-QBmA/G2y+IfeS4oktet3qRZ+P5kPhCKRXxXnQEudYqUaEioAU1/Lq2us3D/t1Jfo4hE9REQPrbB7K5sOczJVIw==" + }, + "mime-types": { + "version": "2.1.30", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.30.tgz", + "integrity": "sha512-crmjA4bLtR8m9qLpHvgxSChT+XoSlZi8J4n/aIdn3z92e/U47Z0V/yl+Wh9W046GgFVAmoNR/fmdbZYcSSIUeg==", + "requires": { + "mime-db": "1.47.0" + } + }, + "node-fetch": { + "version": "2.6.1", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.1.tgz", + "integrity": "sha512-V4aYg89jEoVRxRb2fJdAg8FHvI7cEyYdVAh94HH0UIK8oJxUfkjlDQN9RbMx+bEjP7+ggMiFRprSti032Oipxw==" + }, + "opusscript": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/opusscript/-/opusscript-0.0.8.tgz", + "integrity": "sha512-VSTi1aWFuCkRCVq+tx/BQ5q9fMnQ9pVZ3JU4UHKqTkf0ED3fKEPdr+gKAAl3IA2hj9rrP6iyq3hlcJq3HELtNQ==" + }, + "prism-media": { + "version": "1.2.9", + "resolved": "https://registry.npmjs.org/prism-media/-/prism-media-1.2.9.tgz", + "integrity": "sha512-UHCYuqHipbTR1ZsXr5eg4JUmHER8Ss4YEb9Azn+9zzJ7/jlTtD1h0lc4g6tNx3eMlB8Mp6bfll0LPMAV4R6r3Q==" + }, + "setimmediate": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz", + "integrity": "sha1-KQy7Iy4waULX1+qbg3Mqt4VvgoU=" + }, + "sha1": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/sha1/-/sha1-1.1.1.tgz", + "integrity": "sha1-rdqnqTFo85PxnrKxUJFhjicA+Eg=", + "requires": { + "charenc": ">= 0.0.1", + "crypt": ">= 0.0.1" + } + }, + "tweetnacl": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-1.0.3.tgz", + "integrity": "sha512-6rt+RN7aOi1nGMyC4Xa5DdYiukl2UWCbcJft7YhxReBGQD7OAM8Pbxw6YMo4r2diNEA8FEmu32YOn9rhaiE5yw==" + }, + "ws": { + "version": "7.4.4", + "resolved": "https://registry.npmjs.org/ws/-/ws-7.4.4.tgz", + "integrity": "sha512-Qm8k8ojNQIMx7S+Zp8u/uHOx7Qazv3Yv4q68MiWWWOJhiwG5W3x7iqmRtJo8xxrciZUY4vRxUTJCKuRnF28ZZw==" + } + } +} diff --git a/package.json b/package.json new file mode 100644 index 0000000..62d4f6a --- /dev/null +++ b/package.json @@ -0,0 +1,20 @@ +{ + "name": "tardis-bot", + "version": "1.0.0", + "description": "", + "main": "index.js", + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1" + }, + "keywords": [], + "author": "", + "license": "ISC", + "dependencies": { + "discord.js": "^12.5.3", + "dotenv": "^8.2.0", + "google-tts-api": "^2.0.2", + "node-fetch": "^2.6.1", + "opusscript": "^0.0.8", + "sha1": "^1.1.1" + } +} diff --git a/voice-test.js b/voice-test.js new file mode 100644 index 0000000..48c9ebc --- /dev/null +++ b/voice-test.js @@ -0,0 +1,19 @@ +const tts = require('google-tts-api'); +const fetch = require('node-fetch'); +const fs = require('fs'); +const buffer = require('buffer'); + +async function generateVoice(string) { + const url = tts.getAudioUrl(string, {lang: "en-us"}); + console.log("Generated url: " + url); + const data = await fetch(url); + const contents = await data.arrayBuffer(); + const buf = Buffer.from(contents); + fs.writeFileSync('speak.mp3', buf); +} + +async function test() { + const url = await generateVoice("Hi there bud"); +} + +test(); \ No newline at end of file