From 1706be9cf98337168481a9579c8bd82197604db5 Mon Sep 17 00:00:00 2001 From: Manuel Date: Mon, 18 Jan 2021 23:03:15 +0000 Subject: [PATCH] Initial commit --- .editorconfig | 12 +++++++ .gitignore | 8 +++++ README.md | 23 ++++++++++++ colorbot.config.js | 15 ++++++++ index.js | 90 ++++++++++++++++++++++++++++++++++++++++++++++ package.json | 15 ++++++++ yarn.lock | 60 +++++++++++++++++++++++++++++++ 7 files changed, 223 insertions(+) create mode 100644 .editorconfig create mode 100644 .gitignore create mode 100644 README.md create mode 100644 colorbot.config.js create mode 100644 index.js create mode 100644 package.json create mode 100644 yarn.lock diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000..c59c447 --- /dev/null +++ b/.editorconfig @@ -0,0 +1,12 @@ +root = true + +[*] +indent_style = tab +indent_size = 4 +end_of_line = lf +charset = utf-8 +trim_trailing_whitespace = true +insert_final_newline = true + +[*.md] +trim_trailing_whitespace = false diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..f28075a --- /dev/null +++ b/.gitignore @@ -0,0 +1,8 @@ +node_modules +.vscode +yarn-debug.log* +yarn-error.log* + +*.swp +*.swo +*.DS_Store diff --git a/README.md b/README.md new file mode 100644 index 0000000..d2a224c --- /dev/null +++ b/README.md @@ -0,0 +1,23 @@ +# Twitch Color Bot + +Setup the following environment variables: + +- `TWITCH_BOT_KEY` (required) + - You can generate a key here: https://twitchapps.com/tmi/ +- `TWITCH_BOT_USERNAME` (required) +- `TWITCH_BOT_COLOR_MODE` + - Currently supports `random` and `loop` + - Random will select a random color with varying hue, saturation, and lightness. + - Loop will increment the hue value through the spectrum and loop. +- `TWITCH_BOT_INTERVAL` + - Time between color changes in seconds. Default 10 seconds. + +## Running locally + +Install dependencies with `yarn install`. + +Run app + +```bash +node index.js +``` diff --git a/colorbot.config.js b/colorbot.config.js new file mode 100644 index 0000000..4337d00 --- /dev/null +++ b/colorbot.config.js @@ -0,0 +1,15 @@ +module.exports = { + apps : [ + { + name: "colorbot-twitch", + script: "./index.js", + watch: true, + env: { + "TWITCH_BOT_KEY": "", + "TWITCH_BOT_USERNAME": "", + "TWITCH_BOT_COLOR_MODE": "loop", + "TWITCH_BOT_INTERVAL": 10 + } + } + ] +} \ No newline at end of file diff --git a/index.js b/index.js new file mode 100644 index 0000000..72093ef --- /dev/null +++ b/index.js @@ -0,0 +1,90 @@ +const tmi = require("tmi.js"); +const convert = require("color-convert"); +const chalk = require("chalk"); + +const sleep = (waitTimeInMs) => new Promise(resolve => setTimeout(resolve, waitTimeInMs)); + +let hue = 48; +let sat = 89; +let light = 50; + +let connected = false; + +if (!process.env.TWITCH_BOT_KEY || !process.env.TWITCH_BOT_USERNAME) { + console.log( + "TWITCH_BOT_KEY and TWITCH_BOT_USERNAME must be available as environment variables" + ); + process.exit(1); +} + +const colorMode = process.env.TWITCH_BOT_COLOR_MODE || "loop"; + +const client = new tmi.Client({ + connection: { + reconnect: true, + secure: true + }, + identity: { + username: process.env.TWITCH_BOT_USERNAME, + password: process.env.TWITCH_BOT_KEY + }, + channels: [process.env.TWITCH_BOT_USERNAME.toLowerCase()] +}); + +client.on("connected", onConnected); +client.on("disconnected", onDisconnected); + +client.connect(); + +function onConnected(addr, port) { + console.log(`* Connected to ${addr}:${port}`); + + connected = true; + updateColor(); +} + +function onDisconnected(reason) { + console.log(`* Disconnected: ${reason}`); + + connected = false; +} + +function generateRandomColor() { + hue = Math.floor(Math.random() * 360); + sat = 20 + Math.floor(Math.random() * 60); + light = 40 + Math.floor(Math.random() * 40); +} + +function incrementColorLoop() { + if (hue < 351) { + hue += 2; + } else { + hue = 0; + } +} + +function updateColor() { + if (!connected) { + console.log('tried to update color while not connected.'); + return; + } + + if (colorMode === "random") { + generateRandomColor(); + } else { + incrementColorLoop(); + } + + const color = convert.hsl.hex(hue, sat, light); + console.log( + `* Updating username color to`, + chalk.hex(`#${color}`)(`#${color}`) + ); + client.color(`#${color}`); +} + +const intervalTime = process.env.TWITCH_BOT_INTERVAL * 1000 || 10000; + +interval = setInterval(function () { + updateColor(); +}, intervalTime); diff --git a/package.json b/package.json new file mode 100644 index 0000000..4689a30 --- /dev/null +++ b/package.json @@ -0,0 +1,15 @@ +{ + "name": "colorbot-twitch", + "version": "1.0.0", + "main": "index.js", + "author": "Manuel Hüsers", + "license": "MIT", + "dependencies": { + "chalk": "^4.1.0", + "color-convert": "^2.0.1", + "tmi.js": "^1.5.0" + }, + "scripts": { + "start": "node index.js" + } +} \ No newline at end of file diff --git a/yarn.lock b/yarn.lock new file mode 100644 index 0000000..96946bc --- /dev/null +++ b/yarn.lock @@ -0,0 +1,60 @@ +# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. +# yarn lockfile v1 + + +ansi-styles@^4.1.0: + version "4.3.0" + resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-4.3.0.tgz#edd803628ae71c04c85ae7a0906edad34b648937" + integrity sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg== + dependencies: + color-convert "^2.0.1" + +chalk@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/chalk/-/chalk-4.1.0.tgz#4e14870a618d9e2edd97dd8345fd9d9dc315646a" + integrity sha512-qwx12AxXe2Q5xQ43Ac//I6v5aXTipYrSESdOgzrN+9XjgEpyjpKuvSGaN4qE93f7TQTlerQQ8S+EQ0EyDoVL1A== + dependencies: + ansi-styles "^4.1.0" + supports-color "^7.1.0" + +color-convert@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-2.0.1.tgz#72d3a68d598c9bdb3af2ad1e84f21d896abd4de3" + integrity sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ== + dependencies: + color-name "~1.1.4" + +color-name@~1.1.4: + version "1.1.4" + resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.4.tgz#c2a09a87acbde69543de6f63fa3995c826c536a2" + integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA== + +has-flag@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-4.0.0.tgz#944771fd9c81c81265c4d6941860da06bb59479b" + integrity sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ== + +node-fetch@2.6.1: + version "2.6.1" + resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.1.tgz#045bd323631f76ed2e2b55573394416b639a0052" + integrity sha512-V4aYg89jEoVRxRb2fJdAg8FHvI7cEyYdVAh94HH0UIK8oJxUfkjlDQN9RbMx+bEjP7+ggMiFRprSti032Oipxw== + +supports-color@^7.1.0: + version "7.2.0" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-7.2.0.tgz#1b7dcdcb32b8138801b3e478ba6a51caa89648da" + integrity sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw== + dependencies: + has-flag "^4.0.0" + +tmi.js@^1.5.0: + version "1.7.5" + resolved "https://registry.yarnpkg.com/tmi.js/-/tmi.js-1.7.5.tgz#da5ce238b8bb38c01c3c6717b73441b9f1c8ae84" + integrity sha512-j3kAnJ8KkWbvwhKhQchleyzZEuPa/5rWdeV7MNBEYEAqGhbZuXR+FfI1QgKphYqUrJ4qFAB3WjHG2YlhGq3PDg== + dependencies: + node-fetch "2.6.1" + ws "7.4.3" + +ws@7.4.3: + version "7.4.3" + resolved "https://registry.yarnpkg.com/ws/-/ws-7.4.3.tgz#1f9643de34a543b8edb124bdcbc457ae55a6e5cd" + integrity sha512-hr6vCR76GsossIRsr8OLR9acVVm1jyfEWvhbNjtgPOrfvAlKzvyeg/P6r8RuDjRyrcQoPQT7K0DGEPc7Ae6jzA==