Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add MessageCommand command to Discord bot #20

Merged
merged 3 commits into from
Sep 25, 2022
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
8 changes: 8 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,11 @@ jobs:
- name: Run JQ lint
uses: home-assistant/actions/helpers/jq@master

- name: Setup YQ
uses: chrisdickinson/setup-yq@latest
with:
yq-version: v4.25.3

- name: Use Node.js ${{ env.node-NODE_VERSION }}
uses: actions/setup-node@v3.4.1
with:
Expand All @@ -40,6 +45,9 @@ jobs:
restore-keys: |
${{ runner.os }}-yarn-

- name: Lint YAML files
run: yq '.' ./data/discord_messages.yaml

- name: Install dependencies
run: yarn install --immutable

Expand Down
3 changes: 3 additions & 0 deletions data/discord_messages.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
hello_world:
description: "Print hello world message"
content: "Hello world :wave:"
2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@
"discord.js": "^14.3.0",
"find-up": "^4.0.0",
"graphql": "^16.6.0",
"js-yaml": "^4.1.0",
"nestjs-pino": "^2.5.2",
"node-fetch": "2",
"pino": "^8.4.2",
Expand All @@ -64,6 +65,7 @@
"@nestjs/cli": "^8.2.5",
"@nestjs/schematics": "^8.0.10",
"@nestjs/testing": "^8.4.4",
"@types/js-yaml": "^4",
"@typescript-eslint/eslint-plugin": "5.21.0",
"@typescript-eslint/parser": "^5.21.0",
"eslint": "8.14.0",
Expand Down
124 changes: 124 additions & 0 deletions services/bots/src/discord/commands/message.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,124 @@
import fetch from 'node-fetch';
import yaml from 'js-yaml';

import { TransformPipe } from '@discord-nestjs/common';
import {
DiscordTransformedCommand,
Payload,
TransformedCommandExecutionContext,
Param,
UsePipes,
On,
} from '@discord-nestjs/core';
import { CommandHandler, DiscordCommandClass } from '../discord.decorator';
import { AutocompleteInteraction, EmbedBuilder } from 'discord.js';
import { reportException } from '@lib/sentry/reporting';

const DATA_FILE_URL =
'https://raw.githubusercontent.com/home-assistant/service-hub/main/data/discord_messages.yaml';

interface MessageData {
[key: string]: { description: string; content: string };
}

class MessageDto {
@Param({
name: 'message',
description: 'What message do you want to post?',
required: true,
autocomplete: true,
})
messageKey: string;
}

@DiscordCommandClass({
name: 'message',
description: 'Returns a predefined message',
})
@UsePipes(TransformPipe)
export class MessageCommand implements DiscordTransformedCommand<MessageDto> {
private messageData: MessageData;

async reloadMessageData(force?: boolean): Promise<void> {
if (force || !this.messageData) {
this.messageData = yaml.load(await (await fetch(DATA_FILE_URL)).text(), {
json: true,
}) as MessageData;
}
}
@CommandHandler()
async handler(
@Payload() handlerDto: MessageDto,
context: TransformedCommandExecutionContext,
): Promise<void> {
const { messageKey } = handlerDto;
const { interaction } = context;
if (messageKey === 'reload') {
await this.reloadMessageData(true);

await interaction.reply({
content: 'Message list reloaded',
ephemeral: true,
});
return;
}

if (!this.messageData[messageKey]) {
await interaction.reply({
content: 'Could not find information',
ephemeral: true,
});
return;
}

await this.reloadMessageData();

await interaction.reply({
embeds: [
new EmbedBuilder({
description: this.messageData[messageKey].content,
}),
],
});
}

// This is the autocomplete handler for the /message command
@On('interactionCreate')
async onInteractionCreate(interaction: AutocompleteInteraction): Promise<void> {
if (!interaction.isAutocomplete() || interaction.commandName !== 'message') {
return;
}
try {
await this.reloadMessageData();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we call it ensureMessageDataLoaded

const focusedValue = interaction.options.getFocused()?.toLowerCase();

await interaction.respond(
focusedValue.length !== 0
? Object.entries(this.messageData)
.map(([key, data]) => ({
name: data.description,
value: key,
}))
.filter(
(choice) =>
choice.value.toLowerCase().includes(focusedValue) ||
choice.name.toLowerCase().includes(focusedValue),
)
// The API only allow max 25 sugestions
.slice(0, 25)
: [],
);
} catch (err) {
reportException(err, {
cause: err,
data: {
interaction: interaction.toJSON(),
user: interaction.user.toJSON(),
channel: interaction.channel.toJSON(),
command: interaction.command.toJSON(),
},
});
await interaction.respond([]);
}
}
}
3 changes: 2 additions & 1 deletion services/bots/src/discord/discord.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,10 @@ import { DiscordModule } from '@discord-nestjs/core';
import { PingCommand } from './commands/ping';
import { VersionsCommand } from './commands/versions';
import { IntegrationCommand } from './commands/integration';
import { MessageCommand } from './commands/message';

@Module({
imports: [DiscordModule.forFeature()],
providers: [PingCommand, VersionsCommand, IntegrationCommand],
providers: [PingCommand, VersionsCommand, IntegrationCommand, MessageCommand],
})
export class DiscordBotModule {}
9 changes: 9 additions & 0 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -1475,6 +1475,13 @@ __metadata:
languageName: node
linkType: hard

"@types/js-yaml@npm:^4":
version: 4.0.5
resolution: "@types/js-yaml@npm:4.0.5"
checksum: 7dcac8c50fec31643cc9d6444b5503239a861414cdfaa7ae9a38bc22597c4d850c4b8cec3d82d73b3fbca408348ce223b0408d598b32e094470dfffc6d486b4d
languageName: node
linkType: hard

"@types/json-schema@npm:*, @types/json-schema@npm:^7.0.8, @types/json-schema@npm:^7.0.9":
version: 7.0.11
resolution: "@types/json-schema@npm:7.0.11"
Expand Down Expand Up @@ -6511,6 +6518,7 @@ __metadata:
"@octokit/webhooks-types": ^6.3.6
"@sentry/integrations": ^6.19.7
"@sentry/node": ^6.19.7
"@types/js-yaml": ^4
"@typescript-eslint/eslint-plugin": 5.21.0
"@typescript-eslint/parser": ^5.21.0
apollo-server-express: ^3.6.7
Expand All @@ -6523,6 +6531,7 @@ __metadata:
eslint-plugin-import: ^2.26.0
find-up: ^4.0.0
graphql: ^16.6.0
js-yaml: ^4.1.0
mocha: ^10.0.0
nestjs-pino: ^2.5.2
node-fetch: 2
Expand Down