Browse Source

create bot

master
david 2 years ago
commit
3f5bc6ab9e
  1. 2
      .dockerignore
  2. 41
      .drone.yml
  3. 2
      .gitignore
  4. 5
      Dockerfile
  5. 8
      docker-compose.yml
  6. 192
      index.js
  7. 1964
      package-lock.json
  8. 18
      package.json
  9. 8
      swarm/deploy.bash
  10. 20
      swarm/docker-compose.blenderbot.yml
  11. 2
      swarm/logs.bash
  12. 2
      swarm/remove.bash
  13. 3
      swarm/restart.bash
  14. 2
      swarm/status.bash

2
.dockerignore

@ -0,0 +1,2 @@
node_modules
.env

41
.drone.yml

@ -0,0 +1,41 @@
---
kind: pipeline
name: default
steps:
- name: build blenderbot
image: plugins/docker
settings:
username:
from_secret: docker_username
password:
from_secret: docker_password
repo: daveplsno/blenderbot
tags:
- latest
- '${DRONE_COMMIT_SHA:0:8}'
- name: deploy blenderbot to swarm
image: docker:dind
environment:
DEPLOY_ENV:
from_secret: DEPLOY_ENV
volumes:
- name: dockersock
path: /var/run/docker.sock
commands:
- export $DEPLOY_ENV
- export imageTag='${DRONE_COMMIT_SHA:0:8}'
- docker stack deploy -c ./swarm/docker-compose.blenderbot.yml blenderbot
- docker service update --force --update-parallelism 1 --update-delay 30s blenderbot_bot
volumes:
- name: dockersock
host:
path: /var/run/docker.sock
trigger:
branch:
- master
event:
- push

2
.gitignore vendored

@ -0,0 +1,2 @@
node_modules
**.env*

5
Dockerfile

@ -0,0 +1,5 @@
FROM node:17.3-alpine3.12
WORKDIR /app
COPY index.js package* ./
RUN npm install
CMD ["node", "index.js"]

8
docker-compose.yml

@ -0,0 +1,8 @@
---
version: '2.4'
services:
blenderbot:
build:
context: .
image: daveplsno/blenderbot:latest

192
index.js

@ -0,0 +1,192 @@
import { Client } from 'irc-framework';
import schedule from 'node-schedule';
import { Pushover } from '@hyperlink/pushover';
import dotenv from 'dotenv';
dotenv.config();
const { APP_TOKEN, USER_TOKEN, HOST, PORT, NICK, CHANNEL, BAE, NOTICE_MSG } =
process.env;
const CONFIG = {
CLIENT: {
host: HOST,
port: PORT,
nick: NICK,
username: NICK,
},
CHANNEL_NAME: CHANNEL,
BAE: BAE,
NOTICE_MSG: NOTICE_MSG,
};
async function sendMessage(title, msg) {
console.log('sending msg!');
const pushover = new Pushover(APP_TOKEN, USER_TOKEN);
const msgRes = await pushover.sendMessage({
message: msg,
title: title,
});
if (msgRes?.status === 1)
return console.log(`msg req (${msgRes?.request}) sent successfully`);
return console.log('msg req failed');
}
const delay = (sec) =>
new Promise((resolve) => setTimeout(resolve, sec * 1000));
function getRandomIntInclusive(min, max) {
min = Math.ceil(min);
max = Math.floor(max);
return Math.floor(Math.random() * (max - min + 1) + min);
}
// eg..
// let userList = [
// {
// userNick: 'blenderpls',
// canSpeakTo: true,
// gmbCount: 0,
// msgCount: 0,
// },
// ]
let userList = [];
const bot = new Client();
bot.connect({
...CONFIG.CLIENT,
});
const buffers = [];
bot.on('registered', () => {
const channel = bot.channel(CONFIG.CHANNEL_NAME);
buffers.push(channel);
channel.join();
bot.action(CONFIG.CHANNEL_NAME, CONFIG.NOTICE_MSG);
channel.updateUsers(() => {
// smash all the existing users into the userlist straight away
channel.users.map(
(user) =>
(userList = [
...userList,
{ userNick: user.nick, canSpeakTo: true, gmbCount: 0, msgCount: 0 },
])
);
});
});
const roboCompliments = [
'Are those real or were you upgraded in silicone valley?',
'Are you made of Copper and Tellurium? Because you are Cu-Te',
'Beep Beep Boop Beep Sex',
'Can I have your ip number? I seem to have lost mine.',
`Come with me and I'll insert my floppy into your disk drive.`,
'Commencing explosive containment procedures, why? Because you are the bomb.',
'Do you got a free port for me to plug into?',
'Do you like it when I touch your PCI Slot?',
`Don't worry I just got turing tested.`,
'Hey baby, I am backward compatible, to service all your legacy needs.',
];
// extend array with some sample fnc
Array.prototype.sample = function () {
return this[Math.floor(Math.random() * this.length)];
};
// every minute do smth
// schedule.scheduleJob('*/1 * * * *', () => {});
// at midnight do smth
schedule.scheduleJob('0 0 * * *', () => {
console.log('resetting GMBs!');
userList = userList.map((user) =>
user.gmbCount > 0 ? { ...user, gmbCount: 0 } : user
);
});
// do smth once a week
schedule.scheduleJob('0 0 * * 0', () => {
// basically at the start of the week kick off a randomly scheduled job to give gmbbot a compliment
const roboLove = async () => {
console.log('executing robo love protocols');
// sometime after 4hrs but before 6 days
const randoNumber = getRandomIntInclusive(14400, 518400);
await delay(randoNumber);
bot.channel(CONFIG.CHANNEL_NAME).updateUsers(() => {
const channel = bot.channel(CONFIG.CHANNEL_NAME);
channel.updateUsers(() => {
const checkForGmbBot = channel.users.find(
(user) => user.nick === CONFIG.BAE
);
if (checkForGmbBot)
bot.say(
CONFIG.CHANNEL_NAME,
`${CONFIG.BAE}, ${roboCompliments.sample()}`
);
});
});
};
roboLove();
});
bot.on('message', (event) => {
// get some msg infos
const msg = event.message.toLowerCase();
const fromNick = event.nick.toLowerCase();
// log the server msgs
if (fromNick === '') console.log(fromNick, msg);
// find user infos
let user;
user = userList?.find(({ userNick }) => userNick === fromNick);
if (!user) {
user = { userNick: fromNick, canSpeakTo: true, gmbCount: 0, msgCount: 0 };
userList = [...userList, user];
}
// msgs that expect the bang at the beginning and don't care what follows
if (msg.indexOf('!robocompliment') === 0)
event.reply(`${roboCompliments.sample()}`);
if (msg.indexOf('!alert') === 0)
sendMessage(`msg from ${fromNick}`, event.message);
if (msg.indexOf('!msgcount') === 0)
event.reply(
`${user.userNick} has sent ${user.msgCount} ${
user.msgCount === 1 ? 'msg' : 'msgs'
}`
);
if (msg === '!gmbcount')
event.reply(`${user.userNick} has sent ${user.gmbCount} gmbs today`);
// msgs that only care about matching exactly the string
if (msg === 'gmb') {
if (user.gmbCount === 0) event.reply(`gmb, ${event.nick}`);
userList = userList.map((obj) =>
obj.userNick === fromNick ? { ...obj, gmbCount: obj.gmbCount + 1 } : obj
);
}
// bump that msg count
userList = userList.map((obj) =>
obj.userNick === fromNick ? { ...obj, msgCount: obj.msgCount + 1 } : obj
);
});

1964
package-lock.json generated

File diff suppressed because it is too large Load Diff

18
package.json

@ -0,0 +1,18 @@
{
"name": "blenderbot",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "",
"license": "ISC",
"dependencies": {
"@hyperlink/pushover": "^1.0.0",
"dotenv": "^10.0.0",
"irc-framework": "^4.12.1",
"node-schedule": "^2.1.0"
},
"type": "module"
}

8
swarm/deploy.bash

@ -0,0 +1,8 @@
# export vars
export $(cat .env.deploy)
# deploy to swarm
docker stack deploy -c ./docker-compose.blenderbot.yml --prune blenderbot
# unset the env vars
unset $(cat .env.deploy | cut -f 1 -d '=' $1)

20
swarm/docker-compose.blenderbot.yml

@ -0,0 +1,20 @@
---
version: '3.8'
networks:
swarmnet-public:
external: true
services:
bot:
image: daveplsno/blenderbot:${imageTag? Variable not set}
hostname: blenderbot
env_file: .env.deploy
networks:
- swarmnet-public
deploy:
restart_policy:
condition: on-failure
placement:
constraints:
- node.labels.${blenderbotNode? Variable not set} == true

2
swarm/logs.bash

@ -0,0 +1,2 @@
#!/bin/bash
docker service logs blenderbot_bot -f

2
swarm/remove.bash

@ -0,0 +1,2 @@
#!/bin/bash
docker service rm blenderbot_bot

3
swarm/restart.bash

@ -0,0 +1,3 @@
#!/bin/bash
docker service scale blenderbot_bot=0
docker service scale blenderbot_bot=1

2
swarm/status.bash

@ -0,0 +1,2 @@
#!/bin/bash
docker stack services blenderbot
Loading…
Cancel
Save