-
Notifications
You must be signed in to change notification settings - Fork 32
/
hello-action.ts
149 lines (142 loc) · 4.09 KB
/
hello-action.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
import express from "express";
import { FollowUp, SignatureVerifier } from "../helpers";
import { sleep } from "@collabland/common";
import {
APIChatInputApplicationCommandInteraction,
APIInteractionResponse,
ApplicationCommandOptionType,
ApplicationCommandType,
DiscordActionMetadata,
DiscordActionRequest,
DiscordActionResponse,
getCommandOptionValue,
InteractionResponseType,
InteractionType,
MessageFlags,
RESTPatchAPIWebhookWithTokenMessageJSONBody,
RESTPostAPIWebhookWithTokenJSONBody,
} from "@collabland/discord";
import { MiniAppManifest } from "@collabland/models";
const router = express.Router();
async function handle(
interaction: DiscordActionRequest<APIChatInputApplicationCommandInteraction>
): Promise<DiscordActionResponse> {
/**
* Get the value of `your-name` argument for `/hello-action`
*/
const yourName = getCommandOptionValue(interaction, "your-name");
const message = `Hello, ${
yourName ?? interaction.user?.username ?? "World"
}!`;
/**
* Build a simple Discord message private to the user
*/
const response: APIInteractionResponse = {
type: InteractionResponseType.ChannelMessageWithSource,
data: {
content: message,
flags: MessageFlags.Ephemeral,
},
};
/**
* Allow advanced followup messages
*/
followup(interaction, message).catch((err) => {
console.error(
"Fail to send followup message to interaction %s: %O",
interaction.id,
err
);
});
// Return the 1st response to Discord
return response;
}
async function followup(
request: DiscordActionRequest<APIChatInputApplicationCommandInteraction>,
message: string
) {
const follow = new FollowUp();
const callback = request.actionContext?.callbackUrl;
if (callback != null) {
const followupMsg: RESTPostAPIWebhookWithTokenJSONBody = {
content: `Follow-up: **${message}**`,
flags: MessageFlags.Ephemeral,
};
await sleep(1000);
let msg = await follow.followupMessage(request, followupMsg);
await sleep(1000);
// 5 seconds count down
for (let i = 5; i > 0; i--) {
const updated: RESTPatchAPIWebhookWithTokenMessageJSONBody = {
content: `[${i}s]: **${message}**`,
};
msg = await follow.editMessage(request, updated, msg?.id);
await sleep(1000);
}
// Delete the follow-up message
await follow.deleteMessage(request, msg?.id);
}
}
router.get("/metadata", function (req, res) {
const manifest = new MiniAppManifest({
appId: "hello-action",
developer: "collab.land",
name: "HelloAction",
platforms: ["discord"],
shortName: "hello-action",
version: { name: "0.0.1" },
website: "https://collab.land",
description: "An example Collab.Land action",
});
const metadata: DiscordActionMetadata = {
/**
* Miniapp manifest
*/
manifest,
/**
* Supported Discord interactions. They allow Collab.Land to route Discord
* interactions based on the type and name/custom-id.
*/
supportedInteractions: [
{
// Handle `/hello-action` slash command
type: InteractionType.ApplicationCommand,
names: ["hello-action"],
},
],
/**
* Supported Discord application commands. They will be registered to a
* Discord guild upon installation.
*/
applicationCommands: [
// `/hello-action <your-name>` slash command
{
metadata: {
name: "HelloAction",
shortName: "hello-action",
},
name: "hello-action",
type: ApplicationCommandType.ChatInput,
description: "/hello-action",
options: [
{
name: "your-name",
description: "Name of person we're greeting",
type: ApplicationCommandOptionType.String,
required: true,
},
],
},
],
};
res.send(metadata);
});
router.post("/interactions", async function (req, res) {
const verifier = new SignatureVerifier();
const verified = verifier.verify(req, res);
if (verified) {
const result = await handle(req.body);
res.send(result);
}
});
export default router;