Skip to content

Commit 98464ea

Browse files
committed
docs: bring en and zh to parity
- Translate add-new-group, local-development, requirements, telegram-integration-guide from zh into en - Translate architecture and user-experience walkthrough from en into zh - Mirror user-experience screenshots (page-1/2/3) into zh/user-experience - All command snippets, JSON, and CDK examples preserved verbatim across locales
1 parent ffa91c1 commit 98464ea

9 files changed

Lines changed: 1483 additions & 0 deletions

File tree

docs/en/add-new-group.md

Lines changed: 182 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,182 @@
1+
# How to Create a New Group Photo Wall
2+
3+
This guide explains how to add an independent photo wall for a new Telegram group. Each group requires its own Bot.
4+
5+
---
6+
7+
## Prerequisites
8+
9+
- The project has been deployed at least once (`./deploy.sh` or `npx cdk deploy`)
10+
- AWS CLI is installed and credentials are configured
11+
- You have a Telegram account
12+
13+
---
14+
15+
## Step 1: Create a New Telegram Bot
16+
17+
1. Open Telegram and search for **@BotFather**
18+
2. Send `/newbot`
19+
3. Provide a Bot name (e.g. `Marketing Wall Bot`) and a username (e.g. `marketing_wall_bot`, must end in `bot`)
20+
4. Save the returned **Bot Token**
21+
5. Turn off Privacy Mode: BotFather → `/mybots` → select the Bot → Bot Settings → Group Privacy → **Turn off**
22+
23+
---
24+
25+
## Step 2: Store the Bot Token in Secrets Manager
26+
27+
```bash
28+
aws secretsmanager create-secret \
29+
--name "telegram/bot-token/marketing" \
30+
--secret-string "YOUR_NEW_BOT_TOKEN" \
31+
--region us-west-2
32+
```
33+
34+
> The `marketing` suffix in `telegram/bot-token/marketing` is arbitrary; it just has to match the `secretName` you set in the next step.
35+
36+
---
37+
38+
## Step 3: Add the New Group to `cdk.json`
39+
40+
Edit the project root `cdk.json` and append a new entry to the `telegramGroups` array:
41+
42+
```json
43+
{
44+
"context": {
45+
"telegramGroups": [
46+
{
47+
"groupId": "demo-group",
48+
"chatId": "-1001234567890",
49+
"name": "Demo Photo Wall",
50+
"secretName": "telegram/bot-token/demo-group",
51+
"botUsername": "your_photo_wall_bot"
52+
},
53+
{
54+
"groupId": "marketing",
55+
"chatId": "-1009876543210",
56+
"name": "Marketing Photo Wall",
57+
"secretName": "telegram/bot-token/marketing",
58+
"botUsername": "marketing_wall_bot"
59+
}
60+
]
61+
}
62+
}
63+
```
64+
65+
### Field Reference
66+
67+
| Field | Required | Description | Example |
68+
|-------|----------|-------------|---------|
69+
| `groupId` | Yes | URL identifier for the wall; letters, digits, underscore, hyphen only | `marketing` |
70+
| `chatId` | Yes | Telegram group Chat ID (negative integer); see the appendix for how to obtain it | `-1009876543210` |
71+
| `name` | Yes | Title shown on the photo wall page | `Marketing Photo Wall` |
72+
| `secretName` | Yes | Name in Secrets Manager that holds the Bot Token; must match Step 2 | `telegram/bot-token/marketing` |
73+
| `botUsername` | Yes | The Bot's `@username` (without `@`); only messages that `@mention` it are surfaced on the wall | `marketing_wall_bot` |
74+
75+
---
76+
77+
## Step 4: Deploy
78+
79+
```bash
80+
cd photo-wall && npm run build && cd ..
81+
npx cdk deploy --require-approval never
82+
```
83+
84+
After the deployment, the CDK output prints the new group's webhook URL:
85+
86+
```
87+
TelegramPhotoWallStack.WebhookUrlmarketing = https://<YOUR_DOMAIN>/api/webhook/marketing
88+
```
89+
90+
---
91+
92+
## Step 5: Register the Telegram Webhook
93+
94+
```bash
95+
# Fetch the webhook verification secret
96+
WEBHOOK_SECRET=$(aws secretsmanager get-secret-value \
97+
--secret-id "telegram/webhook-secret" \
98+
--query SecretString --output text \
99+
--region us-west-2)
100+
101+
# Fetch the new Bot Token
102+
NEW_BOT_TOKEN=$(aws secretsmanager get-secret-value \
103+
--secret-id "telegram/bot-token/marketing" \
104+
--query SecretString --output text \
105+
--region us-west-2)
106+
107+
# Register the webhook
108+
curl -X POST "https://api.telegram.org/bot${NEW_BOT_TOKEN}/setWebhook" \
109+
-H "Content-Type: application/json" \
110+
-d "{
111+
\"url\": \"https://<YOUR_DOMAIN>/api/webhook/marketing\",
112+
\"secret_token\": \"${WEBHOOK_SECRET}\",
113+
\"allowed_updates\": [\"message\"]
114+
}"
115+
```
116+
117+
> Replace `https://<YOUR_DOMAIN>` with the actual CloudFront URL emitted by CDK.
118+
119+
### Verify the Webhook
120+
121+
```bash
122+
curl -s "https://api.telegram.org/bot${NEW_BOT_TOKEN}/getWebhookInfo" | python3 -m json.tool
123+
```
124+
125+
---
126+
127+
## Step 6: Add the Bot to the Group
128+
129+
1. Open the target Telegram group
130+
2. Add member → search for `@marketing_wall_bot` → add
131+
3. Send a test message in the group: `@marketing_wall_bot hello`
132+
133+
---
134+
135+
## Step 7: Open the Photo Wall
136+
137+
```
138+
https://<YOUR_DOMAIN>/wall/marketing
139+
```
140+
141+
If multiple groups are configured, a group switcher appears at the top of the page.
142+
143+
---
144+
145+
## Appendix
146+
147+
### Get the Telegram Group Chat ID
148+
149+
**Method 1: Via the Bot API**
150+
151+
1. Add the Bot to the group
152+
2. Send any message in the group
153+
3. Run:
154+
```bash
155+
curl -s "https://api.telegram.org/bot${NEW_BOT_TOKEN}/getUpdates" | python3 -m json.tool
156+
```
157+
4. Locate `message.chat.id` in the returned JSON (group Chat IDs are negative, e.g. `-1009876543210`)
158+
159+
**Method 2: Via @userinfobot**
160+
161+
1. Add `@userinfobot` to the group
162+
2. It will reply with the group's Chat ID
163+
3. Remove it once you have the value
164+
165+
### Remove a Group
166+
167+
1. Remove the entry from `telegramGroups` in `cdk.json`
168+
2. Redeploy: `npx cdk deploy`
169+
3. (Optional) Delete the Bot Token: `aws secretsmanager delete-secret --secret-id "telegram/bot-token/marketing" --region us-west-2`
170+
4. (Optional) Remove the webhook: `curl -X POST "https://api.telegram.org/bot${NEW_BOT_TOKEN}/deleteWebhook"`
171+
172+
### Quick Reference
173+
174+
| Step | Command / Action |
175+
|------|------------------|
176+
| 1. Create the Bot | BotFather `/newbot` + turn off Privacy Mode |
177+
| 2. Store the Token | `aws secretsmanager create-secret ...` |
178+
| 3. Update config | Edit `cdk.json`, append the new group |
179+
| 4. Deploy | `npx cdk deploy` |
180+
| 5. Register webhook | `curl ... setWebhook` |
181+
| 6. Add Bot to group | Add as a Telegram group member |
182+
| 7. Test | Send `@bot hello` in the group, open `/wall/groupId` |

docs/en/local-development.md

Lines changed: 163 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,163 @@
1+
# Local Development Guide
2+
3+
## How It Works
4+
5+
For local development, Next.js runs on your machine but **connects directly to the deployed AWS resources** (DynamoDB, S3, Secrets Manager). No local database is required.
6+
7+
```
8+
Local Next.js (localhost:3000)
9+
├── read/write → AWS DynamoDB (the same table used in production)
10+
├── read/write → AWS S3 (the same bucket used in production)
11+
└── read → AWS Secrets Manager (Bot Token)
12+
13+
Telegram → ngrok → localhost:3000 (only when debugging the webhook)
14+
```
15+
16+
## Prerequisites
17+
18+
- Node.js 20+
19+
- AWS CLI with configured credentials (`aws configure`) that can access the deployed resources
20+
- (Optional) [ngrok](https://ngrok.com/) — only needed when debugging the Telegram webhook
21+
22+
## Quick Start
23+
24+
### 1. Generate the Local Environment File
25+
26+
```bash
27+
# Pull every resource ID from the deployed CDK stack
28+
./scripts/setup-local-env.sh
29+
```
30+
31+
The script writes `photo-wall/.env.local`, which looks like:
32+
33+
```env
34+
AWS_REGION_NAME=us-west-2
35+
TABLE_NAME=TelegramPhotoWallStack-MessagesTable05B58A27-xxxxx
36+
BUCKET_NAME=telegramphotowallstack-photobucket465738b3-xxxxx
37+
WEBHOOK_SECRET_ARN=arn:aws:secretsmanager:us-west-2:xxxxx:secret:telegram/webhook-secret-xxxxx
38+
GROUP_CONFIG=[{"groupId":"demo-group","chatId":"-1001234567890","name":"Demo Photo Wall","secretName":"telegram/bot-token/demo-group"}]
39+
```
40+
41+
> If you have not deployed the stack yet, run `./deploy.sh` first.
42+
43+
### 2. Start the Dev Server
44+
45+
```bash
46+
cd photo-wall
47+
npm install # only on first run or when dependencies change
48+
npm run dev
49+
```
50+
51+
Open http://localhost:3000/wall/demo-group to view the photo wall.
52+
53+
**Hot reload**: edits to frontend components (TSX/CSS) refresh the browser automatically; edits to API routes apply on the next request.
54+
55+
### 3. Debug the Telegram Webhook (optional)
56+
57+
If you need to debug incoming Telegram messages locally, expose your local port to the internet with ngrok:
58+
59+
```bash
60+
# Terminal 1: start ngrok
61+
ngrok http 3000
62+
63+
# Note the public URL it prints, e.g. https://abcd1234.ngrok-free.app
64+
```
65+
66+
```bash
67+
# Terminal 2: point the Telegram webhook at your ngrok URL
68+
./scripts/set-webhook-local.sh https://abcd1234.ngrok-free.app
69+
```
70+
71+
Telegram messages in the group will now flow to your local Next.js server.
72+
73+
**When you're done, restore the production webhook:**
74+
75+
```bash
76+
./scripts/set-webhook-prod.sh
77+
```
78+
79+
## Common Workflows
80+
81+
### Frontend-only Changes (Styles / Interactions)
82+
83+
Edit files under `photo-wall/src/components/` or `photo-wall/src/app/`. The browser hot-reloads. ngrok is not required, and existing messages load via the API as usual.
84+
85+
### API Changes (Message Queries)
86+
87+
Edit files under `photo-wall/src/app/api/messages/` and refresh the page to test. Data is read from the deployed DynamoDB table.
88+
89+
### Webhook Changes (Inbound Messages)
90+
91+
This requires ngrok plus switching the webhook to your local URL. You can also simulate Telegram requests with curl:
92+
93+
```bash
94+
# Fetch the webhook secret
95+
WEBHOOK_SECRET=$(aws secretsmanager get-secret-value \
96+
--secret-id "telegram/webhook-secret" \
97+
--query SecretString --output text --region us-west-2)
98+
99+
# Simulate a text message
100+
curl -X POST http://localhost:3000/api/webhook/demo-group \
101+
-H "Content-Type: application/json" \
102+
-H "X-Telegram-Bot-Api-Secret-Token: $WEBHOOK_SECRET" \
103+
-d '{
104+
"update_id": 12345,
105+
"message": {
106+
"message_id": 999,
107+
"from": {"id": 123, "first_name": "Test"},
108+
"chat": {"id": -1001234567890},
109+
"date": 1700000000,
110+
"text": "Hello from local dev"
111+
}
112+
}'
113+
114+
# Simulate a photo message (file_id is fake; download will fail but the row is persisted)
115+
curl -X POST http://localhost:3000/api/webhook/demo-group \
116+
-H "Content-Type: application/json" \
117+
-H "X-Telegram-Bot-Api-Secret-Token: $WEBHOOK_SECRET" \
118+
-d '{
119+
"update_id": 12346,
120+
"message": {
121+
"message_id": 1000,
122+
"from": {"id": 123, "first_name": "Test"},
123+
"chat": {"id": -1001234567890},
124+
"date": 1700000001,
125+
"photo": [
126+
{"file_id": "fake_small", "file_unique_id": "u1", "width": 90, "height": 90},
127+
{"file_id": "fake_large", "file_unique_id": "u2", "width": 800, "height": 600}
128+
],
129+
"caption": "Test photo"
130+
}
131+
}'
132+
```
133+
134+
### CDK Infrastructure Changes
135+
136+
```bash
137+
# Preview the diff
138+
npx cdk diff
139+
140+
# Apply the change
141+
npx cdk deploy
142+
143+
# Refresh the local env file if any resource names changed
144+
./scripts/setup-local-env.sh
145+
```
146+
147+
## Project Layout
148+
149+
```
150+
telegram-photo-wall/
151+
├── photo-wall/ ← Next.js application (where local dev happens)
152+
│ ├── src/app/api/ ← API routes (webhook, messages, health)
153+
│ ├── src/components/ ← React components (photo wall UI)
154+
│ ├── src/lib/ ← Utilities (AWS clients, config, sanitization)
155+
│ ├── .env.local ← Local env file (gitignored)
156+
│ └── package.json
157+
├── lib/ ← CDK infrastructure definitions
158+
├── scripts/
159+
│ ├── setup-local-env.sh ← Generate .env.local
160+
│ ├── set-webhook-local.sh ← Webhook → ngrok (local debugging)
161+
│ └── set-webhook-prod.sh ← Webhook → CloudFront (restore production)
162+
└── cdk.json ← Group configuration
163+
```

0 commit comments

Comments
 (0)