@fluxy-chat/create-fluxy-chat 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.ts +1 -0
- package/dist/index.js +946 -0
- package/package.json +45 -0
- package/readme.md +89 -0
- package/templates/basic/package.json +19 -0
- package/templates/basic/readme.md +36 -0
- package/templates/basic/src/bot.ts +40 -0
- package/templates/basic/src/index.ts +17 -0
- package/templates/basic/tsconfig.json +18 -0
- package/templates/basic/wrangler.toml +9 -0
- package/templates/discord/package.json +20 -0
- package/templates/discord/readme.md +37 -0
- package/templates/discord/src/bot.ts +59 -0
- package/templates/discord/src/index.ts +17 -0
- package/templates/slack/package.json +21 -0
- package/templates/slack/readme.md +37 -0
- package/templates/slack/src/bot.ts +58 -0
- package/templates/slack/src/index.ts +19 -0
- package/templates/telegram/package.json +20 -0
- package/templates/telegram/readme.md +39 -0
- package/templates/telegram/src/bot.ts +47 -0
- package/templates/telegram/src/index.ts +18 -0
package/package.json
ADDED
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@fluxy-chat/create-fluxy-chat",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"type": "module",
|
|
5
|
+
"main": "./dist/index.js",
|
|
6
|
+
"bin": {
|
|
7
|
+
"create-fluxy-chat": "./dist/index.js"
|
|
8
|
+
},
|
|
9
|
+
"engines": {
|
|
10
|
+
"node": "\u003e=20.12"
|
|
11
|
+
},
|
|
12
|
+
"files": [
|
|
13
|
+
"dist",
|
|
14
|
+
"templates",
|
|
15
|
+
"README.md"
|
|
16
|
+
],
|
|
17
|
+
"scripts": {
|
|
18
|
+
"build": "tsup src/index.ts --format esm --dts",
|
|
19
|
+
"dev": "tsup src/index.ts --format esm --watch",
|
|
20
|
+
"typecheck": "tsc --noEmit",
|
|
21
|
+
"prepublishOnly": "pnpm run build"
|
|
22
|
+
},
|
|
23
|
+
"dependencies": {
|
|
24
|
+
"@clack/prompts": "^0.7.0",
|
|
25
|
+
"picocolors": "^1.1.1"
|
|
26
|
+
},
|
|
27
|
+
"devDependencies": {
|
|
28
|
+
"@types/node": "^22.0.0",
|
|
29
|
+
"tsup": "^8.3.5",
|
|
30
|
+
"typescript": "^5.6.0"
|
|
31
|
+
},
|
|
32
|
+
"repository": {
|
|
33
|
+
"type": "git",
|
|
34
|
+
"url": "git+https://github.com/AlessandroFare/fluxychat.git",
|
|
35
|
+
"directory": "packages/create-fluxy-chat"
|
|
36
|
+
},
|
|
37
|
+
"homepage": "https://github.com/AlessandroFare/fluxychat/tree/main/packages/create-fluxy-chat#readme",
|
|
38
|
+
"bugs": {
|
|
39
|
+
"url": "https://github.com/AlessandroFare/fluxychat/issues"
|
|
40
|
+
},
|
|
41
|
+
"publishConfig": {
|
|
42
|
+
"access": "public"
|
|
43
|
+
},
|
|
44
|
+
"license": "MIT"
|
|
45
|
+
}
|
package/readme.md
ADDED
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
# create-fluxy-chat
|
|
2
|
+
|
|
3
|
+
Scaffold a new [FluxyChat](https://github.com/AlessandroFare/fluxychat) bot project with a single command.
|
|
4
|
+
|
|
5
|
+
## Quick Start
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npx create-fluxy-chat my-bot
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
This launches an interactive prompt to configure your bot project.
|
|
12
|
+
|
|
13
|
+
## Non-Interactive Usage
|
|
14
|
+
|
|
15
|
+
```bash
|
|
16
|
+
# Create a Slack bot with pnpm
|
|
17
|
+
npx create-fluxy-chat my-bot --adapter slack --pm pnpm
|
|
18
|
+
|
|
19
|
+
# Create a Telegram bot, skip install
|
|
20
|
+
npx create-fluxy-chat my-bot --adapter telegram --skip-install
|
|
21
|
+
|
|
22
|
+
# Create a Discord bot with defaults
|
|
23
|
+
npx create-fluxy-chat my-bot -y --adapter discord
|
|
24
|
+
|
|
25
|
+
# Create a basic webhook bot
|
|
26
|
+
npx create-fluxy-chat my-bot --adapter basic
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
## Options
|
|
30
|
+
|
|
31
|
+
| Flag | Short | Description |
|
|
32
|
+
| --- | --- | --- |
|
|
33
|
+
| `--adapter <type>` | `-a` | Adapter: `basic`, `slack`, `telegram`, `discord`, `web` |
|
|
34
|
+
| `--pm <manager>` | | Package manager: `npm`, `pnpm`, `yarn` |
|
|
35
|
+
| `--language <lang>` | `-l` | Language: `typescript` (default) or `javascript` |
|
|
36
|
+
| `--yes` | `-y` | Skip prompts and accept defaults |
|
|
37
|
+
| `--skip-install` | | Skip dependency installation |
|
|
38
|
+
| `--no-git` | | Skip git repository initialization |
|
|
39
|
+
| `--help` | `-h` | Show help |
|
|
40
|
+
|
|
41
|
+
## Adapters
|
|
42
|
+
|
|
43
|
+
| Adapter | Description | Platform |
|
|
44
|
+
| --- | --- | --- |
|
|
45
|
+
| `basic` | Generic webhook bot | Cloudflare Workers |
|
|
46
|
+
| `slack` | Slack Events API bot | Slack |
|
|
47
|
+
| `telegram` | Telegram webhook bot | Telegram |
|
|
48
|
+
| `discord` | Discord interactions bot | Discord |
|
|
49
|
+
| `web` | Web chat HTTP API bot | Any HTTP client |
|
|
50
|
+
|
|
51
|
+
## What You Get
|
|
52
|
+
|
|
53
|
+
Each generated project includes:
|
|
54
|
+
|
|
55
|
+
- **`src/index.ts`** — Cloudflare Workers entry point with route handling
|
|
56
|
+
- **`src/bot.ts`** — Bot handler using `@fluxy-chat/sdk`
|
|
57
|
+
- **`wrangler.toml`** — Cloudflare Workers deployment config
|
|
58
|
+
- **`.dev.vars`** — Local development environment variables
|
|
59
|
+
- **`.env.example`** — Example environment variables for your adapter
|
|
60
|
+
- **`tsconfig.json`** — TypeScript configuration (for TS projects)
|
|
61
|
+
- **`README.md`** — Project-specific setup instructions
|
|
62
|
+
- **`.gitignore`** — Standard ignore patterns
|
|
63
|
+
|
|
64
|
+
## Package Manager Detection
|
|
65
|
+
|
|
66
|
+
The CLI auto-detects your package manager from lockfiles:
|
|
67
|
+
|
|
68
|
+
- `pnpm-lock.yaml` → pnpm
|
|
69
|
+
- `yarn.lock` → yarn
|
|
70
|
+
- `package-lock.json` or none → npm
|
|
71
|
+
|
|
72
|
+
You can override with `--pm`.
|
|
73
|
+
|
|
74
|
+
## Development
|
|
75
|
+
|
|
76
|
+
```bash
|
|
77
|
+
# Install dependencies
|
|
78
|
+
pnpm install
|
|
79
|
+
|
|
80
|
+
# Build the CLI
|
|
81
|
+
pnpm build
|
|
82
|
+
|
|
83
|
+
# Run locally
|
|
84
|
+
node dist/index.js my-test-bot -y --adapter basic
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
## License
|
|
88
|
+
|
|
89
|
+
MIT
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "fluxy-bot-basic",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"type": "module",
|
|
5
|
+
"private": true,
|
|
6
|
+
"scripts": {
|
|
7
|
+
"dev": "wrangler dev",
|
|
8
|
+
"deploy": "wrangler deploy",
|
|
9
|
+
"type-check": "tsc --noEmit"
|
|
10
|
+
},
|
|
11
|
+
"dependencies": {
|
|
12
|
+
"@fluxy-chat/sdk": "latest"
|
|
13
|
+
},
|
|
14
|
+
"devDependencies": {
|
|
15
|
+
"@cloudflare/workers-types": "^4.0.0",
|
|
16
|
+
"typescript": "^5.6.0",
|
|
17
|
+
"wrangler": "^3.0.0"
|
|
18
|
+
}
|
|
19
|
+
}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
# fluxy-bot-basic
|
|
2
|
+
|
|
3
|
+
A basic webhook bot built with [FluxyChat](https://github.com/AlessandroFare/fluxychat) and deployed on Cloudflare Workers.
|
|
4
|
+
|
|
5
|
+
## Getting Started
|
|
6
|
+
|
|
7
|
+
1. Copy the example environment file:
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
cp .env.example .dev.vars
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
2. Start the dev server:
|
|
14
|
+
|
|
15
|
+
```bash
|
|
16
|
+
pnpm dev
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
3. Deploy to Cloudflare Workers:
|
|
20
|
+
|
|
21
|
+
```bash
|
|
22
|
+
pnpm deploy
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
## Endpoints
|
|
26
|
+
|
|
27
|
+
- Health check: `/`
|
|
28
|
+
- Webhook: `/webhook`
|
|
29
|
+
|
|
30
|
+
## Environment Variables
|
|
31
|
+
|
|
32
|
+
See `.env.example` for all required environment variables.
|
|
33
|
+
|
|
34
|
+
## License
|
|
35
|
+
|
|
36
|
+
MIT
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { FluxyChatClient } from "@fluxy-chat/sdk";
|
|
2
|
+
|
|
3
|
+
interface BotEnv {
|
|
4
|
+
FLUXY_BASE_URL: string;
|
|
5
|
+
FLUXY_API_KEY: string;
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
export async function handleWebhook(
|
|
9
|
+
request: Request,
|
|
10
|
+
env: BotEnv,
|
|
11
|
+
): Promise<Response> {
|
|
12
|
+
const body = await request.json() as {
|
|
13
|
+
roomId?: string;
|
|
14
|
+
message?: string;
|
|
15
|
+
userId?: string;
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
const client = new FluxyChatClient({
|
|
19
|
+
baseUrl: env.FLUXY_BASE_URL,
|
|
20
|
+
userId: body.userId ?? "bot",
|
|
21
|
+
apiKey: env.FLUXY_API_KEY,
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
try {
|
|
25
|
+
if (body.roomId && body.message) {
|
|
26
|
+
await client.createMessage(body.roomId, body.message);
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
return new Response(
|
|
30
|
+
JSON.stringify({ ok: true }),
|
|
31
|
+
{ status: 200, headers: { "Content-Type": "application/json" } },
|
|
32
|
+
);
|
|
33
|
+
} catch (error) {
|
|
34
|
+
console.error("Webhook error:", error);
|
|
35
|
+
return new Response(
|
|
36
|
+
JSON.stringify({ error: "Internal server error" }),
|
|
37
|
+
{ status: 500, headers: { "Content-Type": "application/json" } },
|
|
38
|
+
);
|
|
39
|
+
}
|
|
40
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { handleWebhook } from "./bot.js";
|
|
2
|
+
|
|
3
|
+
export default {
|
|
4
|
+
async fetch(request: Request, env: Record<string, string>): Promise<Response> {
|
|
5
|
+
const url = new URL(request.url);
|
|
6
|
+
|
|
7
|
+
if (url.pathname === "/webhook" && request.method === "POST") {
|
|
8
|
+
return handleWebhook(request, env);
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
if (url.pathname === "/") {
|
|
12
|
+
return new Response("FluxyChat bot is running!", { status: 200 });
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
return new Response("Not Found", { status: 404 });
|
|
16
|
+
},
|
|
17
|
+
};
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
{
|
|
2
|
+
"compilerOptions": {
|
|
3
|
+
"target": "ES2022",
|
|
4
|
+
"module": "ESNext",
|
|
5
|
+
"moduleResolution": "bundler",
|
|
6
|
+
"lib": ["ES2022"],
|
|
7
|
+
"types": ["@cloudflare/workers-types"],
|
|
8
|
+
"strict": true,
|
|
9
|
+
"esModuleInterop": true,
|
|
10
|
+
"skipLibCheck": true,
|
|
11
|
+
"forceConsistentCasingInFileNames": true,
|
|
12
|
+
"resolveJsonModule": true,
|
|
13
|
+
"allowSyntheticDefaultImports": true,
|
|
14
|
+
"noEmit": true
|
|
15
|
+
},
|
|
16
|
+
"include": ["src/**/*"],
|
|
17
|
+
"exclude": ["node_modules", "dist"]
|
|
18
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "fluxy-bot-discord",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"type": "module",
|
|
5
|
+
"private": true,
|
|
6
|
+
"scripts": {
|
|
7
|
+
"dev": "wrangler dev",
|
|
8
|
+
"deploy": "wrangler deploy",
|
|
9
|
+
"type-check": "tsc --noEmit"
|
|
10
|
+
},
|
|
11
|
+
"dependencies": {
|
|
12
|
+
"@fluxy-chat/sdk": "latest",
|
|
13
|
+
"discord.js": "^14.0.0"
|
|
14
|
+
},
|
|
15
|
+
"devDependencies": {
|
|
16
|
+
"@cloudflare/workers-types": "^4.0.0",
|
|
17
|
+
"typescript": "^5.6.0",
|
|
18
|
+
"wrangler": "^3.0.0"
|
|
19
|
+
}
|
|
20
|
+
}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
# fluxy-bot-discord
|
|
2
|
+
|
|
3
|
+
A Discord bot built with [FluxyChat](https://github.com/AlessandroFare/fluxychat) and deployed on Cloudflare Workers.
|
|
4
|
+
|
|
5
|
+
## Getting Started
|
|
6
|
+
|
|
7
|
+
1. Copy the example environment file:
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
cp .env.example .dev.vars
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
2. Create a Discord application at https://discord.com/developers/applications and get your bot token, application ID, and public key.
|
|
14
|
+
|
|
15
|
+
3. Start the dev server:
|
|
16
|
+
|
|
17
|
+
```bash
|
|
18
|
+
pnpm dev
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
4. Set the Discord Interactions Endpoint URL to point to your worker's `/discord/interactions` endpoint.
|
|
22
|
+
|
|
23
|
+
## Endpoints
|
|
24
|
+
|
|
25
|
+
- Discord Interactions: `/discord/interactions`
|
|
26
|
+
|
|
27
|
+
## Environment Variables
|
|
28
|
+
|
|
29
|
+
- `FLUXY_BASE_URL` — Your FluxyChat worker URL
|
|
30
|
+
- `FLUXY_API_KEY` — FluxyChat API key
|
|
31
|
+
- `DISCORD_BOT_TOKEN` — Discord bot token
|
|
32
|
+
- `DISCORD_APPLICATION_ID` — Discord application ID
|
|
33
|
+
- `DISCORD_PUBLIC_KEY` — Discord public key (for signature verification)
|
|
34
|
+
|
|
35
|
+
## License
|
|
36
|
+
|
|
37
|
+
MIT
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import { FluxyChatClient } from "@fluxy-chat/sdk";
|
|
2
|
+
|
|
3
|
+
interface BotEnv {
|
|
4
|
+
FLUXY_BASE_URL: string;
|
|
5
|
+
FLUXY_API_KEY: string;
|
|
6
|
+
DISCORD_BOT_TOKEN: string;
|
|
7
|
+
DISCORD_PUBLIC_KEY: string;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
export async function handleDiscordInteraction(
|
|
11
|
+
request: Request,
|
|
12
|
+
env: BotEnv,
|
|
13
|
+
): Promise<Response> {
|
|
14
|
+
const body = await request.text();
|
|
15
|
+
|
|
16
|
+
const client = new FluxyChatClient({
|
|
17
|
+
baseUrl: env.FLUXY_BASE_URL,
|
|
18
|
+
userId: "discord-bot",
|
|
19
|
+
apiKey: env.FLUXY_API_KEY,
|
|
20
|
+
});
|
|
21
|
+
|
|
22
|
+
try {
|
|
23
|
+
const interaction = JSON.parse(body);
|
|
24
|
+
|
|
25
|
+
// Handle Discord ping (verification)
|
|
26
|
+
if (interaction.type === 1) {
|
|
27
|
+
return new Response(JSON.stringify({ type: 1 }), {
|
|
28
|
+
headers: { "Content-Type": "application/json" },
|
|
29
|
+
});
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
// Handle application command
|
|
33
|
+
if (interaction.type === 2) {
|
|
34
|
+
const commandName = interaction.data?.name;
|
|
35
|
+
|
|
36
|
+
if (commandName === "chat") {
|
|
37
|
+
const userId = interaction.member?.user?.id ?? interaction.user?.id ?? "unknown";
|
|
38
|
+
const text = interaction.data?.options?.[0]?.value ?? "";
|
|
39
|
+
|
|
40
|
+
// Forward to FluxyChat
|
|
41
|
+
const roomId = `discord-${interaction.channel_id}`;
|
|
42
|
+
await client.createMessage(roomId, String(text));
|
|
43
|
+
|
|
44
|
+
return new Response(
|
|
45
|
+
JSON.stringify({
|
|
46
|
+
type: 4,
|
|
47
|
+
data: { content: "Message forwarded to FluxyChat!" },
|
|
48
|
+
}),
|
|
49
|
+
{ headers: { "Content-Type": "application/json" } },
|
|
50
|
+
);
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
return new Response("Unknown interaction type", { status: 400 });
|
|
55
|
+
} catch (error) {
|
|
56
|
+
console.error("Discord interaction error:", error);
|
|
57
|
+
return new Response("Internal Server Error", { status: 500 });
|
|
58
|
+
}
|
|
59
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { handleDiscordInteraction } from "./bot.js";
|
|
2
|
+
|
|
3
|
+
export default {
|
|
4
|
+
async fetch(request: Request, env: Record<string, string>): Promise<Response> {
|
|
5
|
+
const url = new URL(request.url);
|
|
6
|
+
|
|
7
|
+
if (url.pathname === "/discord/interactions" && request.method === "POST") {
|
|
8
|
+
return handleDiscordInteraction(request, env);
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
if (url.pathname === "/") {
|
|
12
|
+
return new Response("FluxyChat Discord bot is running!", { status: 200 });
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
return new Response("Not Found", { status: 404 });
|
|
16
|
+
},
|
|
17
|
+
};
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "fluxy-bot-slack",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"type": "module",
|
|
5
|
+
"private": true,
|
|
6
|
+
"scripts": {
|
|
7
|
+
"dev": "wrangler dev",
|
|
8
|
+
"deploy": "wrangler deploy",
|
|
9
|
+
"type-check": "tsc --noEmit"
|
|
10
|
+
},
|
|
11
|
+
"dependencies": {
|
|
12
|
+
"@fluxy-chat/sdk": "latest",
|
|
13
|
+
"@slack/bolt": "^4.0.0",
|
|
14
|
+
"@slack/web-api": "^7.0.0"
|
|
15
|
+
},
|
|
16
|
+
"devDependencies": {
|
|
17
|
+
"@cloudflare/workers-types": "^4.0.0",
|
|
18
|
+
"typescript": "^5.6.0",
|
|
19
|
+
"wrangler": "^3.0.0"
|
|
20
|
+
}
|
|
21
|
+
}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
# fluxy-bot-slack
|
|
2
|
+
|
|
3
|
+
A Slack bot built with [FluxyChat](https://github.com/AlessandroFare/fluxychat) and deployed on Cloudflare Workers.
|
|
4
|
+
|
|
5
|
+
## Getting Started
|
|
6
|
+
|
|
7
|
+
1. Copy the example environment file:
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
cp .env.example .dev.vars
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
2. Create a Slack app at https://api.slack.com/apps and get your bot token and signing secret.
|
|
14
|
+
|
|
15
|
+
3. Start the dev server:
|
|
16
|
+
|
|
17
|
+
```bash
|
|
18
|
+
pnpm dev
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
4. Set up the Slack Event Subscriptions URL to point to your worker's `/slack/events` endpoint.
|
|
22
|
+
|
|
23
|
+
## Endpoints
|
|
24
|
+
|
|
25
|
+
- Slack Events API: `/slack/events`
|
|
26
|
+
- Slack Interactive: `/slack/interactive`
|
|
27
|
+
|
|
28
|
+
## Environment Variables
|
|
29
|
+
|
|
30
|
+
- `FLUXY_BASE_URL` — Your FluxyChat worker URL
|
|
31
|
+
- `FLUXY_API_KEY` — FluxyChat API key
|
|
32
|
+
- `SLACK_BOT_TOKEN` — Slack bot token (xoxb-...)
|
|
33
|
+
- `SLACK_SIGNING_SECRET` — Slack signing secret
|
|
34
|
+
|
|
35
|
+
## License
|
|
36
|
+
|
|
37
|
+
MIT
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import { FluxyChatClient } from "@fluxy-chat/sdk";
|
|
2
|
+
|
|
3
|
+
interface BotEnv {
|
|
4
|
+
FLUXY_BASE_URL: string;
|
|
5
|
+
FLUXY_API_KEY: string;
|
|
6
|
+
SLACK_BOT_TOKEN: string;
|
|
7
|
+
SLACK_SIGNING_SECRET: string;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
export interface SlackBot {
|
|
11
|
+
fluxyClient: FluxyChatClient;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export function createSlackBot(): SlackBot {
|
|
15
|
+
return {
|
|
16
|
+
fluxyClient: null as unknown as FluxyChatClient,
|
|
17
|
+
};
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export async function handleSlackRequest(
|
|
21
|
+
request: Request,
|
|
22
|
+
env: BotEnv,
|
|
23
|
+
bot: SlackBot,
|
|
24
|
+
): Promise<Response> {
|
|
25
|
+
const body = await request.text();
|
|
26
|
+
|
|
27
|
+
const client = new FluxyChatClient({
|
|
28
|
+
baseUrl: env.FLUXY_BASE_URL,
|
|
29
|
+
userId: "slack-bot",
|
|
30
|
+
apiKey: env.FLUXY_API_KEY,
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
try {
|
|
34
|
+
const payload = JSON.parse(body);
|
|
35
|
+
|
|
36
|
+
// Handle Slack URL verification challenge
|
|
37
|
+
if (payload.type === "url_verification") {
|
|
38
|
+
return new Response(JSON.stringify({ challenge: payload.challenge }), {
|
|
39
|
+
headers: { "Content-Type": "application/json" },
|
|
40
|
+
});
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
// Handle events
|
|
44
|
+
if (payload.event) {
|
|
45
|
+
const event = payload.event;
|
|
46
|
+
|
|
47
|
+
if (event.type === "message" && !event.bot_id) {
|
|
48
|
+
const roomId = `slack-${event.channel}`;
|
|
49
|
+
await client.createMessage(roomId, event.text || "");
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
return new Response("OK", { status: 200 });
|
|
54
|
+
} catch (error) {
|
|
55
|
+
console.error("Slack event error:", error);
|
|
56
|
+
return new Response("Internal Server Error", { status: 500 });
|
|
57
|
+
}
|
|
58
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { handleSlackRequest, createSlackBot } from "./bot.js";
|
|
2
|
+
|
|
3
|
+
const bot = createSlackBot();
|
|
4
|
+
|
|
5
|
+
export default {
|
|
6
|
+
async fetch(request: Request, env: Record<string, string>): Promise<Response> {
|
|
7
|
+
const url = new URL(request.url);
|
|
8
|
+
|
|
9
|
+
if (url.pathname === "/slack/events" || url.pathname === "/slack/interactive") {
|
|
10
|
+
return handleSlackRequest(request, env, bot);
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
if (url.pathname === "/") {
|
|
14
|
+
return new Response("FluxyChat Slack bot is running!", { status: 200 });
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
return new Response("Not Found", { status: 404 });
|
|
18
|
+
},
|
|
19
|
+
};
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "fluxy-bot-telegram",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"type": "module",
|
|
5
|
+
"private": true,
|
|
6
|
+
"scripts": {
|
|
7
|
+
"dev": "wrangler dev",
|
|
8
|
+
"deploy": "wrangler deploy",
|
|
9
|
+
"type-check": "tsc --noEmit"
|
|
10
|
+
},
|
|
11
|
+
"dependencies": {
|
|
12
|
+
"@fluxy-chat/sdk": "latest",
|
|
13
|
+
"node-telegram-bot-api": "^0.66.0"
|
|
14
|
+
},
|
|
15
|
+
"devDependencies": {
|
|
16
|
+
"@cloudflare/workers-types": "^4.0.0",
|
|
17
|
+
"typescript": "^5.6.0",
|
|
18
|
+
"wrangler": "^3.0.0"
|
|
19
|
+
}
|
|
20
|
+
}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
# fluxy-bot-telegram
|
|
2
|
+
|
|
3
|
+
A Telegram bot built with [FluxyChat](https://github.com/AlessandroFare/fluxychat) and deployed on Cloudflare Workers.
|
|
4
|
+
|
|
5
|
+
## Getting Started
|
|
6
|
+
|
|
7
|
+
1. Copy the example environment file:
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
cp .env.example .dev.vars
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
2. Create a Telegram bot via [@BotFather](https://t.me/BotFather) and get your bot token.
|
|
14
|
+
|
|
15
|
+
3. Start the dev server:
|
|
16
|
+
|
|
17
|
+
```bash
|
|
18
|
+
pnpm dev
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
4. Set the Telegram webhook to point to your worker's `/telegram/webhook` endpoint:
|
|
22
|
+
|
|
23
|
+
```bash
|
|
24
|
+
curl "https://api.telegram.org/bot<YOUR_BOT_TOKEN>/setWebhook?url=https://your-worker.example.com/telegram/webhook"
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
## Endpoints
|
|
28
|
+
|
|
29
|
+
- Telegram Webhook: `/telegram/webhook`
|
|
30
|
+
|
|
31
|
+
## Environment Variables
|
|
32
|
+
|
|
33
|
+
- `FLUXY_BASE_URL` — Your FluxyChat worker URL
|
|
34
|
+
- `FLUXY_API_KEY` — FluxyChat API key
|
|
35
|
+
- `TELEGRAM_BOT_TOKEN` — Telegram bot token from BotFather
|
|
36
|
+
|
|
37
|
+
## License
|
|
38
|
+
|
|
39
|
+
MIT
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { FluxyChatClient } from "@fluxy-chat/sdk";
|
|
2
|
+
|
|
3
|
+
interface BotEnv {
|
|
4
|
+
FLUXY_BASE_URL: string;
|
|
5
|
+
FLUXY_API_KEY: string;
|
|
6
|
+
TELEGRAM_BOT_TOKEN: string;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
export async function handleTelegramUpdate(
|
|
10
|
+
update: Record<string, unknown>,
|
|
11
|
+
env: BotEnv,
|
|
12
|
+
): Promise<Response> {
|
|
13
|
+
const client = new FluxyChatClient({
|
|
14
|
+
baseUrl: env.FLUXY_BASE_URL,
|
|
15
|
+
userId: "telegram-bot",
|
|
16
|
+
apiKey: env.FLUXY_API_KEY,
|
|
17
|
+
});
|
|
18
|
+
|
|
19
|
+
try {
|
|
20
|
+
const message = update.message as
|
|
21
|
+
| { chat?: { id?: number }; text?: string; from?: { first_name?: string } }
|
|
22
|
+
| undefined;
|
|
23
|
+
|
|
24
|
+
if (message?.chat?.id && message.text) {
|
|
25
|
+
const roomId = `telegram-${message.chat.id}`;
|
|
26
|
+
|
|
27
|
+
// Forward to FluxyChat
|
|
28
|
+
await client.createMessage(roomId, message.text);
|
|
29
|
+
|
|
30
|
+
// Send reply back to Telegram
|
|
31
|
+
const telegramApiUrl = `https://api.telegram.org/bot${env.TELEGRAM_BOT_TOKEN}/sendMessage`;
|
|
32
|
+
await fetch(telegramApiUrl, {
|
|
33
|
+
method: "POST",
|
|
34
|
+
headers: { "Content-Type": "application/json" },
|
|
35
|
+
body: JSON.stringify({
|
|
36
|
+
chat_id: message.chat.id,
|
|
37
|
+
text: `Hi ${message.from?.first_name ?? "there"}! Message received.`,
|
|
38
|
+
}),
|
|
39
|
+
});
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
return new Response("OK", { status: 200 });
|
|
43
|
+
} catch (error) {
|
|
44
|
+
console.error("Telegram update error:", error);
|
|
45
|
+
return new Response("Internal Server Error", { status: 500 });
|
|
46
|
+
}
|
|
47
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { handleTelegramUpdate } from "./bot.js";
|
|
2
|
+
|
|
3
|
+
export default {
|
|
4
|
+
async fetch(request: Request, env: Record<string, string>): Promise<Response> {
|
|
5
|
+
const url = new URL(request.url);
|
|
6
|
+
|
|
7
|
+
if (url.pathname === "/telegram/webhook" && request.method === "POST") {
|
|
8
|
+
const update = await request.json();
|
|
9
|
+
return handleTelegramUpdate(update, env);
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
if (url.pathname === "/") {
|
|
13
|
+
return new Response("FluxyChat Telegram bot is running!", { status: 200 });
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
return new Response("Not Found", { status: 404 });
|
|
17
|
+
},
|
|
18
|
+
};
|