Skip to content

Instantly share code, notes, and snippets.

@kognise
Created February 1, 2020 20:11
Show Gist options
  • Save kognise/e5b8df52a9f125f6940c97ef1f1a89fc to your computer and use it in GitHub Desktop.
Save kognise/e5b8df52a9f125f6940c97ef1f1a89fc to your computer and use it in GitHub Desktop.
module.exports = {
tokens: [
// Put in a token from https://api.slack.com/legacy/custom-integrations/legacy-tokens
],
name: 'Botnise', // Change the bot name
color: '#f03e3e',
timeout: 10000,
statsFile: 'stats.json',
automations: [
{
match: /(^| )uwu/i,
response: 'UwU'
},
{
match: /(^| )owo($| )/i,
response: 'OwO'
},
{
match: /beep boop/i,
response: 'boop beep?'
},
{
match: /^rofl$/i,
response: 'I am rolling on the floor laughing as well, fellow relatable human.'
},
{
match: / rofl$/i,
response: 'lmaoo'
},
{
match: /minecraft/i,
response: 'OWO DID SOMEONE SAY MINCERAFT :minecraft:'
},
{
match: /^:salute:$/,
response: ':salute:'
},
{
match: /(^| )hm+($| )/i,
response: ':thonk:'
},
{
match: /^:eyes:$/,
response: ':eyes:'
},
{
match: /(^| )bruh+($| )/i,
response: 'bruh lol'
},
{
match: /(^| )lmf?ao+($| )/i,
response: 'lolol'
},
{
match: /(^| )l(o|u|e)l+($| )/i,
responses: [ 'lmao', 'lmaoooo', 'bruh' ]
},
{
match: /botnise/,
responses: [
'botnise is propoganda spread by the fake news media, I am a real person',
'BOTNISE IS A LIE AND A SCAM',
'stop saying botnise, botnise is fake and I am real',
'shhhhhhh'
]
},
{
match: /^holy shit$/i,
responses: [ 'yes', 'yass' ]
},
{
match: /^what is this (((crazy|mad)ness)|(nonsense))$/i,
responses: [ 'good question', 'GOOD QUESTION', 'good question lul' ]
},
{
match: /:b:/,
response: ':b:'
},
{
match: /(^| )(:oof:|oof)$/i,
response: 'oof'
}
]
}
const { RTMClient } = require('@slack/rtm-api')
const { WebClient } = require('@slack/web-api')
const humanize = require('humanize-duration')
const fs = require('fs')
const config = require('./config')
const startup = Date.now()
const stats = fs.existsSync(config.statsFile)
? JSON.parse(fs.readFileSync(config.statsFile))
: {}
const saveStats = () => {
fs.writeFileSync(config.statsFile, JSON.stringify(stats))
}
const start = async (token) => {
const rtm = new RTMClient(token)
const web = new WebClient(token)
const { self, team } = await rtm.start()
console.log(`> Bot started in ${team.name} (${team.id})`)
if (!stats[team.id]) {
stats[team.id] = {
lastMessage: 0,
messages: 0,
userMessages: 0,
botMessages: 0
}
saveStats()
}
const getStatsBlocks = () => [
{
type: 'section',
text: {
type: 'mrkdwn',
text: `:slack: *${config.name} Statistics* (${team.name})`
}
},
{
type: 'section',
fields: [
{
type: 'mrkdwn',
text: `:clock1: Uptime: *${humanize(Date.now() - startup, { conjunction: ' and ', largest: 2 })}*`
},
{
type: 'mrkdwn',
text: `:eyes: Messages: *${stats[team.id].messages}*`
},
{
type: 'mrkdwn',
text: `:sunglasses: Your Messages: *${stats[team.id].userMessages}*`
},
{
type: 'mrkdwn',
text: `:robot_face: My Messages: *${stats[team.id].botMessages} (${Math.round((stats[team.id].botMessages / stats[team.id].userMessages) * 100)}%)*`
}
]
}
]
const getDoxBlocks = (info) => [
{
type: 'section',
text: {
type: 'mrkdwn',
text: `:tada: *Info on <@${info.id}>*`
}
},
{
type: 'section',
fields: [
{
type: 'mrkdwn',
text: `Name: *${info.real_name}*`
},
{
type: 'mrkdwn',
text: `Timezone: *${info.tz_label}*`
},
{
type: 'mrkdwn',
text: `Email: *${info.profile.email || 'N/A'}*`
},
{
type: 'mrkdwn',
text: `Phone #: *${info.profile.phone || 'N/A'}*`
},
{
type: 'mrkdwn',
text: `Title: *${info.profile.title || 'N/A'}*`
},
{
type: 'mrkdwn',
text: `Status: *${info.profile.status_emoji ? info.profile.status_emoji + ' ' : ''}${info.profile.status_text || 'N/A'}*`
}
],
accessory: {
type: 'image',
image_url: info.profile.image_192,
alt_text: `${info.name}'s avatar`
}
}
]
rtm.on('message', async (event) => {
if (event.subtype) return
stats[team.id].messages++
if (event.user === self.id) {
stats[team.id].userMessages++
}
if (event.user === self.id && /^!stats($|\s+)/i.test(event.text)) {
console.log('> Processing stats command')
stats[team.id].botMessages++
await web.chat.postMessage({
channel: event.channel,
thread_ts: event.thread_ts,
attachments: [
{
color: config.color,
blocks: getStatsBlocks()
}
],
as_user: true
})
saveStats()
return
}
const matches = event.text.match(/<@(U[A-Z1-9]{8})>/)
const user = matches ? matches[1] : event.user
if ((event.user === user || event.user === self.id) && /^!(user|uinfo|dox)($|\s+)/i.test(event.text)) {
console.log('> Processing dox command')
stats[team.id].botMessages++
let info
try {
info = await web.users.info({ user })
} catch (error) {
info = {
ok: false,
error: error.message
}
}
if (!info.ok) {
await web.chat.postMessage({
channel: event.channel,
thread_ts: event.thread_ts,
text: `:warning: ${info.error}`,
as_user: true
})
} else {
await web.chat.postMessage({
channel: event.channel,
thread_ts: event.thread_ts,
attachments: [
{
color: config.color,
blocks: getDoxBlocks(info.user)
}
],
as_user: true
})
}
return
}
const ratelimited = Date.now() - stats[team.id].lastMessage < config.timeout
if (ratelimited || event.user === self.id) return
for (let { match, responses, response } of config.automations) {
if (match.test(event.text)) {
if (responses) {
response = responses[Math.floor(Math.random() * responses.length)]
}
await web.chat.postMessage({
channel: event.channel,
thread_ts: event.thread_ts,
text: response,
as_user: true
})
stats[team.id].botMessages++
stats[team.id].lastMessage = Date.now()
saveStats()
return
}
}
saveStats()
})
}
for (let token of config.tokens) {
start(token)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment