Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .dockerignore
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
node_modules
.eslintrc.json
eslint.config.mjs
.gitignore
*.md
.github
.do
test
docs
10 changes: 5 additions & 5 deletions .github/workflows/docker.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -13,18 +13,18 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v3
uses: actions/checkout@v4
- name: Set up QEMU
uses: docker/setup-qemu-action@v2
uses: docker/setup-qemu-action@v3
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v2
uses: docker/setup-buildx-action@v3
- name: Login to DockerHub
uses: docker/login-action@v2
uses: docker/login-action@v3
with:
username: ${{ github.repository_owner }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
- name: Build and push ava
uses: docker/build-push-action@v4
uses: docker/build-push-action@v6
with:
platforms: ${{ env.PLATFORMS }}
push: true
Expand Down
7 changes: 5 additions & 2 deletions .github/workflows/test.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,13 @@ jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
- name: Install Node
uses: actions/setup-node@v3
uses: actions/setup-node@v4
with:
node-version: 'lts/*'
- run: npm ci
- run: npm run lint
env:
CI: true
- run: npm test
7 changes: 4 additions & 3 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
FROM node
FROM node:22-alpine
ENV NODE_ENV=production
WORKDIR /usr/src/app
COPY package.json package-lock.json ./
RUN npm ci --omit=dev
COPY . .
RUN npm install
CMD ["npm", "start"]
CMD ["node", "--no-deprecation", "./index.js"]
27 changes: 25 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
[![alt text](https://img.shields.io/badge/Invite%20To-Discord%20-blue)](https://discord.com/api/oauth2/authorize?client_id=876487225716662302&permissions=34359863296&scope=bot)
![Build Status](https://github.com/circa10a/ava/workflows/publish/badge.svg)

A discord implementation of the famous ava bot
A discord and slack implementation of the famous ava bot

<img src="https://i.imgur.com/XbO6CSl.jpg" width="40%"/>

Expand All @@ -13,8 +13,21 @@ A discord implementation of the famous ava bot

## Usage

Ava starts whichever platforms have tokens configured. Set Discord tokens, Slack tokens, or both to run them simultaneously.

```bash
# Discord only
export AVA_DISCORD_TOKEN=<token>

# Slack only
export AVA_SLACK_BOT_TOKEN=<bot-token>
export AVA_SLACK_APP_TOKEN=<app-level-token>

# Both platforms simultaneously
export AVA_DISCORD_TOKEN=<token>
export AVA_SLACK_BOT_TOKEN=<bot-token>
export AVA_SLACK_APP_TOKEN=<app-level-token>

npm i
npm start
```
Expand All @@ -24,7 +37,10 @@ npm start
| | | |
|----------------------------|----------|---------|
| Environment Variable | Required | Default |
| `AVA_DISCORD_TOKEN` | Yes | `""` |
| `AVA_DISCORD_TOKEN` | Yes (Discord) | `""` |
| `AVA_SLACK_BOT_TOKEN` | Yes (Slack) | `""` |
| `AVA_SLACK_APP_TOKEN` | Yes (Slack) | `""` |
| `AVA_SLACK_SIGNING_SECRET` | No | `""` |
| `AVA_DB_DIR` | No | `./` |
| `AVA_ENABLE_REMINDERS` | No | `false` |
| `AVA_REDDIT_CLIENT_ID` | No | `""` |
Expand Down Expand Up @@ -66,7 +82,14 @@ npm start
## Docker

```bash
# Discord only
docker run -e AVA_DISCORD_TOKEN="<token>" circa10a/ava

# Slack only
docker run -e AVA_SLACK_BOT_TOKEN="<bot-token>" -e AVA_SLACK_APP_TOKEN="<app-token>" circa10a/ava

# Both platforms simultaneously
docker run -e AVA_DISCORD_TOKEN="<token>" -e AVA_SLACK_BOT_TOKEN="<bot-token>" -e AVA_SLACK_APP_TOKEN="<app-token>" circa10a/ava
```

## Contribution
Expand Down
49 changes: 26 additions & 23 deletions commands/8ball.js
Original file line number Diff line number Diff line change
@@ -1,33 +1,36 @@
import { Events } from 'discord.js';
import eightball from '8ball';
import { messageForAva , splitArgs, getAllArgsAsStr, getFileName } from '../lib/utils/utils.js';
import dammit from 'dammit';
import { randomItemFromArray, getAllArgsAsStr, getFileName } from '../lib/utils/utils.js';

const command = getFileName(import.meta.url);

const eightBallResponses = [
'It is certain', 'It is decidedly so', 'Without a doubt',
'Yes definitely', 'You may rely on it', 'As I see it, yes',
'Most likely', 'Outlook good', 'Yes', 'Signs point to yes',
'Reply hazy try again', 'Ask again later', 'Better not tell you now',
'Cannot predict now', 'Concentrate and ask again',
'Don\'t count on it', 'My reply is no', 'My sources say no',
'Outlook not so good', 'Very doubtful',
];

const dammitPhrases = [
'Dammit', 'Damn', 'Damnit', 'Well damn', 'Oh damn',
'Son of a bitch', 'Hell', 'Crap', 'Shit', 'Bloody hell',
'For fuck\'s sake', 'What the hell', 'God dammit',
];

export default {
commandName: command,
name: Events.MessageCreate,
once: false,
execute: async(message) => {
// Ensure message is intended for ava
if (!messageForAva(message)) {
return;
}
const args = splitArgs(message);
const userCmd = args[1];
execute: async (message, args) => {
const question = getAllArgsAsStr(args);

if (userCmd === command) {
if (!question) {
message.reply('No question provided');
return;
}
try {
message.reply(`${dammit({NSFW: true})}... ${eightball()}`);
} catch(e) {
message.channel.send(`\`\`\`log\n${e.toString()}\`\`\``);
}
if (!question) {
message.reply('No question provided');
return;
}
try {
message.reply(`${randomItemFromArray(dammitPhrases)}... ${randomItemFromArray(eightBallResponses)}`);
} catch(e) {
message.channel.send(`\`\`\`log\n${e.toString()}\`\`\``);
}
}
};
39 changes: 13 additions & 26 deletions commands/bored.js
Original file line number Diff line number Diff line change
@@ -1,36 +1,23 @@
import { Events } from 'discord.js';
import fetch from 'node-fetch';
import { messageForAva, splitArgs, getFileName} from '../lib/utils/utils.js';
import { getFileName } from '../lib/utils/utils.js';

const command = getFileName(import.meta.url);

const boredEndpoint = 'https://boredapi.com/api/activity';

export default {
commandName: command,
name: Events.MessageCreate,
once: false,
execute: async(message) => {
// Ensure message is intended for ava
if (!messageForAva(message)) {
return;
}
const args = splitArgs(message);
const userCmd = args[1];

if (userCmd === command) {
try {
const response = await fetch(boredEndpoint, {
method: 'get',
headers: {
'Accept': 'application/json',
}
});
const jsonResponse = await response.json();
message.reply(jsonResponse.activity);
} catch(e) {
message.channel.send(`\`\`\`log\n${e.toString()}\`\`\``);
}
execute: async (message) => {
try {
const response = await fetch(boredEndpoint, {
method: 'get',
headers: {
'Accept': 'application/json',
}
});
const jsonResponse = await response.json();
message.reply(jsonResponse.activity);
} catch(e) {
message.channel.send(`\`\`\`log\n${e.toString()}\`\`\``);
}
}
};
75 changes: 32 additions & 43 deletions commands/brewery.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import { EmbedBuilder, Events } from 'discord.js';
import fetch from 'node-fetch';
import { EmbedBuilder } from 'discord.js';
import { embedColor } from '../config/config.js';
import { randomItemFromArray, messageForAva, splitArgs, getFileName } from '../lib/utils/utils.js';
import { randomItemFromArray, getFileName } from '../lib/utils/utils.js';

const command = getFileName(import.meta.url);

Expand All @@ -10,50 +9,40 @@ const beerThumbnail = 'https://i.imgur.com/6ZKnMaw.jpg';

export default {
commandName: command,
name: Events.MessageCreate,
once: false,
execute: async(message) => {
// Ensure message is intended for ava
if (!messageForAva(message)) {
return;
}
const args = splitArgs(message);
const userCmd = args[1];
execute: async (message, args) => {
const city = args[2];

if (userCmd === command) {
if (!city) {
message.reply('No city provided');
return;
}
try {
const response = await fetch(`${breweryEndpoint}?by_city=${city}`, {
method: 'get',
headers: {
'Accept': 'application/json',
}
});
const breweries = await response.json();
const randomBrewery = randomItemFromArray(breweries);
if (!randomBrewery) {
message.reply('City not found');
return;
if (!city) {
message.reply('No city provided');
return;
}
try {
const response = await fetch(`${breweryEndpoint}?by_city=${city}`, {
method: 'get',
headers: {
'Accept': 'application/json',
}
const embed = new EmbedBuilder()
.setColor(embedColor)
.setTitle(randomBrewery.name)
.setURL(randomBrewery.website_url)
.setDescription(`${randomBrewery.street}\n${randomBrewery.city}, ${randomBrewery.state}`)
.setThumbnail(beerThumbnail)
.addFields(
{ name: 'Google Maps Link', value: `https://www.google.com/maps?q=${randomBrewery.latitude},${randomBrewery.longitude}`},
{ name: 'Phone', value: randomBrewery.phone ?? 'Not listed' },
{ name: 'Brewery Type', value: randomBrewery.brewery_type ?? 'Not listed' },
);
message.channel.send({ embeds: [embed] });
} catch(e) {
message.channel.send(`\`\`\`log\n${e.toString()}\`\`\``);
});
const breweries = await response.json();
const randomBrewery = randomItemFromArray(breweries);
if (!randomBrewery) {
message.reply('City not found');
return;
}
const embed = new EmbedBuilder()
.setColor(embedColor)
.setTitle(randomBrewery.name)
.setURL(randomBrewery.website_url)
.setDescription(`${randomBrewery.street}\n${randomBrewery.city}, ${randomBrewery.state}`)
.setThumbnail(beerThumbnail)
.addFields(
{ name: 'Google Maps Link', value: `https://www.google.com/maps?q=${randomBrewery.latitude},${randomBrewery.longitude}`},
{ name: 'Phone', value: randomBrewery.phone ?? 'Not listed' },
{ name: 'Brewery Type', value: randomBrewery.brewery_type ?? 'Not listed' },
);
message.channel.send({ embeds: [embed] });
} catch(e) {
message.channel.send(`\`\`\`log\n${e.toString()}\`\`\``);
}
}
};
39 changes: 13 additions & 26 deletions commands/catfact.js
Original file line number Diff line number Diff line change
@@ -1,36 +1,23 @@
import { Events } from 'discord.js';
import fetch from 'node-fetch';
import { messageForAva, splitArgs, getFileName } from '../lib/utils/utils.js';
import { getFileName } from '../lib/utils/utils.js';

const command = getFileName(import.meta.url);

const catFactEndpoint = 'https://catfact.ninja/fact';

export default {
commandName: command,
name: Events.MessageCreate,
once: false,
execute: async(message) => {
// Ensure message is intended for ava
if (!messageForAva(message)) {
return;
}
const args = splitArgs(message);
const userCmd = args[1];

if (userCmd === command) {
try {
const response = await fetch(catFactEndpoint, {
method: 'get',
headers: {
'Accept': 'application/json',
}
});
const jsonResponse = await response.json();
message.reply(jsonResponse.fact);
} catch(e) {
message.channel.send(`\`\`\`log\n${e.toString()}\`\`\``);
}
execute: async (message) => {
try {
const response = await fetch(catFactEndpoint, {
method: 'get',
headers: {
'Accept': 'application/json',
}
});
const jsonResponse = await response.json();
message.reply(jsonResponse.fact);
} catch(e) {
message.channel.send(`\`\`\`log\n${e.toString()}\`\`\``);
}
}
};
Loading