Skip to content

Commit f53cc84

Browse files
committedSep 2, 2022
Upload discord bot implementation
1 parent 0ef97ef commit f53cc84

File tree

6 files changed

+721
-1
lines changed

6 files changed

+721
-1
lines changed
 

‎lit-dev.code-workspace

+4
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,10 @@
2424
"name": "lit-dev-server",
2525
"path": "packages/lit-dev-server"
2626
},
27+
{
28+
"name": "lit-dev-discord-bot",
29+
"path": "packages/lit-dev-discord-bot"
30+
},
2731
{
2832
"name": "lit.dev",
2933
"path": "."

‎package-lock.json

+523-1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
+44
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
{
2+
"name": "lit-dev-discord-bot",
3+
"private": true,
4+
"version": "0.0.0",
5+
"description": "the lit bot on the Lit Discord!",
6+
"author": "Google LLC",
7+
"license": "BSD-3-Clause",
8+
"type": "module",
9+
"main": "lib/index.js",
10+
"module": "lib/index.js",
11+
"scripts": {
12+
"build": "wireit",
13+
"start": "wireit"
14+
},
15+
"wireit": {
16+
"build": {
17+
"command": "tsc",
18+
"files": [
19+
"src/**/*.ts"
20+
],
21+
"output": [
22+
"lib/**/*.js"
23+
]
24+
},
25+
"start": {
26+
"command": "node ./lib/index.js",
27+
"files": [
28+
"lib/**/*.ts",
29+
"../../pulic-vars.json"
30+
],
31+
"dependencies": [
32+
"build"
33+
]
34+
}
35+
},
36+
"dependencies": {
37+
"algoliasearch": "^4.14.2",
38+
"discord.js": "^14.3.0"
39+
},
40+
"devDependencies": {
41+
"typescript": "^4.8.2",
42+
"wireit": "^0.7.1"
43+
}
44+
}
+136
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,136 @@
1+
/**
2+
* @license
3+
* Copyright 2022 Google LLC
4+
* SPDX-License-Identifier: BSD-3-Clause
5+
*/
6+
7+
import {
8+
ChatInputCommandInteraction,
9+
Client,
10+
GatewayIntentBits,
11+
InteractionType,
12+
REST,
13+
Routes,
14+
SlashCommandBuilder,
15+
} from 'discord.js';
16+
import algolia from 'algoliasearch/lite.js';
17+
import {publicVars} from 'lit-dev-tools-esm/lib/configs.js';
18+
19+
// set up algolia search
20+
const algClient = algolia(
21+
publicVars.algolia.appId,
22+
publicVars.algolia.searchOnlyKey
23+
);
24+
const index = algClient.initIndex(publicVars.algolia.index);
25+
26+
// The is the GH action secret under the name LIT_DEV_DISCORD_BOT_CLIENT_TOKEN
27+
const BOT_CLIENT_SECRET = process.env.BOT_CLIENT_SECRET;
28+
29+
if (!BOT_CLIENT_SECRET) {
30+
throw new Error('Missing BOT_CLIENT_SECRET');
31+
}
32+
33+
interface Suggestion {
34+
id: number;
35+
relativeUrl: string;
36+
heading: string;
37+
isSubsection: boolean;
38+
title: string;
39+
}
40+
41+
// Build the UI for the slash command.
42+
const command = new SlashCommandBuilder()
43+
.setName('docs')
44+
.setDescription('Will search lit.dev.')
45+
.addStringOption((option) =>
46+
option
47+
.setName('query')
48+
.setDescription('The query to search for.')
49+
.setRequired(true)
50+
.setAutocomplete(true)
51+
);
52+
53+
const rest = new REST({version: '10'}).setToken(BOT_CLIENT_SECRET);
54+
55+
(async () => {
56+
try {
57+
console.log('Started refreshing application (/) commands.');
58+
59+
// Tell Discord that we publish the following slash commands.
60+
await rest.put(Routes.applicationCommands(publicVars.discord.clientId), {
61+
body: [command],
62+
});
63+
64+
console.log('Successfully reloaded application (/) commands.');
65+
} catch (error) {
66+
console.error(error);
67+
}
68+
})();
69+
70+
const client = new Client({intents: [GatewayIntentBits.Guilds]});
71+
72+
client.on('ready', () => {
73+
console.log(`Logged in as ${client.user?.tag}!`);
74+
});
75+
76+
client.on('interactionCreate', async (interaction) => {
77+
if ((interaction as ChatInputCommandInteraction).commandName !== 'docs') {
78+
return;
79+
}
80+
81+
// This happens as the user is typing. Enabled by the SlashCommandBuilder's
82+
// .setAutocomplete(true) option.
83+
if (interaction.type === InteractionType.ApplicationCommandAutocomplete) {
84+
const focusedValue = interaction.options.getFocused();
85+
// Do not waste a query if the user has fewer than 3 chars.
86+
if (focusedValue.length < 3) {
87+
await interaction.respond([]);
88+
return;
89+
}
90+
91+
// Search algolia for the query.
92+
const searchRes = await index.search<Suggestion>(focusedValue, {
93+
page: 0,
94+
hitsPerPage: 5,
95+
});
96+
97+
// Transform the hits' relative URL to objects that are readable and
98+
// linkable outside of lit.dev.
99+
const results = searchRes.hits.map((hit) => {
100+
const readableText = hit.isSubsection
101+
? `${hit.title} - ${hit.heading}`
102+
: hit.title;
103+
104+
// autocomplete requires a `name` and a `value` property like a <select>
105+
// The name is what is shown to the user, but the `value` is what is
106+
// actually sent to the bot in the `.isChatInputCommand()` event.
107+
return {
108+
name: readableText,
109+
value: `https://lit.dev${hit.relativeUrl}`,
110+
};
111+
});
112+
113+
await interaction.respond(results);
114+
}
115+
116+
// This is true when the user finally returns a command. (a lit.dev url)
117+
if (interaction.isChatInputCommand()) {
118+
const value = interaction.options.data[0].value as string;
119+
120+
// If the response is a lit.dev URL then tell the bot to post it.
121+
if (value.startsWith('https://lit.dev')) {
122+
await interaction.reply({content: value});
123+
} else {
124+
// If the response is not a lit.dev url, then bot responds with an
125+
// ephemeral message that is only visible to the user. This happens when
126+
// there are no results, or if the user hits enter before results show up.
127+
interaction.reply({
128+
ephemeral: true,
129+
content: `value: "${value}" is not a valid lit.dev url. Please select from the autocomplete list.`,
130+
});
131+
}
132+
}
133+
});
134+
135+
// Start the web socket connection to the Bot.
136+
client.login(BOT_CLIENT_SECRET);
+11
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
{
2+
"extends": "../../tsconfig.base.json",
3+
"compilerOptions": {
4+
"rootDir": "src",
5+
"outDir": "lib",
6+
"incremental": true,
7+
"tsBuildInfoFile": "lib/.tsbuildinfo"
8+
},
9+
"include": ["src/**/*.ts"],
10+
"exclude": []
11+
}

‎packages/lit-dev-tools-esm/src/configs.ts

+3
Original file line numberDiff line numberDiff line change
@@ -4,4 +4,7 @@ export const publicVars = {
44
searchOnlyKey: '33401c252374747a39ef3b42c9f701ac',
55
index: 'lit.dev',
66
},
7+
discord: {
8+
clientId: '1014381267212574730',
9+
},
710
};

0 commit comments

Comments
 (0)
Please sign in to comment.