Files
chat/.sw
T

247 строки
6.1 KiB
XML

# WSChat development state snapshot
Project: WSChat
Repository: https://github.com/viktor138irk/chat
Default branch: main
## Mandatory rule
Always update this `.sw` file after meaningful code, deployment, architecture, or debugging changes.
Never store secrets in this file: no Telegram tokens, proxy passwords, API keys, SSH credentials, or similar values. Use `[REDACTED]`.
## Product
Self-hosted live chat similar to Jivo. Website widget sends visitor messages to Telegram operators. Operators reply in Telegram, and replies will later return to the website widget.
## Deployment
```text
widget/admin: https://widget.stackworks.ru/
admin panel: https://widget.stackworks.ru/admin/
backend API: https://api.stackworks.ru/health
backend local: http://127.0.0.1:3000
PM2 process: wschat-backend
source: /opt/ws-chat/source
data: /opt/ws-chat/data
SQLite: /opt/ws-chat/data/chat.sqlite
webroot: /var/www/widget_stack_usr/data/www/widget.stackworks.ru
```
MVP architecture is VPS-only. Raspberry Pi was removed from MVP because of Node.js/OS/DPKG instability.
## Database and settings
Correct DB path:
```text
/opt/ws-chat/data/chat.sqlite
```
Production fallback DB path was fixed to the same value even if `.env` is not loaded.
`/health` now includes `dbPath`; it must show:
```text
/opt/ws-chat/data/chat.sqlite
```
Settings come from SQLite table `settings`, not from frontend.
Important keys:
```text
telegram.bot_token
telegram.proxy.enabled
telegram.proxy.type
telegram.proxy.host
telegram.proxy.port
telegram.proxy.username
telegram.proxy.password
```
Diagnostics:
```bash
sqlite3 /opt/ws-chat/data/chat.sqlite "select key, value from settings where key like 'telegram.proxy.%';"
sqlite3 /opt/ws-chat/data/chat.sqlite "select key, length(value) as len from settings where key='telegram.bot_token';"
find /opt/ws-chat/source -name "chat.sqlite"
```
If a DB exists inside `/opt/ws-chat/source/backend/data/`, that was a wrong fallback DB from older code.
## Current endpoints
```text
GET /health
GET /api/config/public
GET /api/admin/stats
GET /api/admin/messages?limit=50
GET /api/admin/telegram/settings
POST /api/admin/telegram/settings
POST /api/admin/telegram/test-proxy
POST /api/admin/telegram/restart
POST /api/widget/message
GET /ws
```
Expected `/health` includes:
```text
ok=true
service=wschat-backend
env=production
dbPath=/opt/ws-chat/data/chat.sqlite
telegram.enabled=true
telegram.running=true
telegram.error=
telegram.proxyEnabled=true
telegram.hasBot=true
```
## Admin panel
Implemented:
- dashboard stats/messages;
- Telegram/SOCKS5 settings form;
- dirty-state protection so refresh does not wipe settings while typing;
- token/password masks;
- save/test/reset actions.
Important: admin loads Telegram settings from `GET /api/admin/telegram/settings`, which reads SQLite.
## Telegram bridge
Runtime file:
```text
backend/src/telegram.js
```
Dependencies:
```text
telegraf
socks-proxy-agent
node-fetch
```
Implemented:
- bridge startup from SQLite settings;
- SOCKS5 proxy support;
- `/start` registers operator;
- `/status` replies with bridge state;
- visitor messages go to active Telegram operators;
- Telegram reply can be saved as operator message when replying to WSChat notification.
Not finished yet:
- delivery of Telegram replies back to widget via WebSocket.
Important proxy fix:
```text
Telegram bridge must use socks5h:// so DNS resolution goes through proxy.
```
## Current debugging status
Current observed Telegram error:
```text
409 Conflict: terminated by other getUpdates request; make sure that only one bot instance is running
```
Meaning: Telegram token/proxy are usable, but two polling instances are running for the same bot token.
Most likely cause: a manual `node src/server.js` process was started during debugging and is still alive while PM2 also runs `wschat-backend`.
Fix on VPS:
```bash
pkill -f "/opt/ws-chat/source/backend/src/server.js" || true
pkill -f "node src/server.js" || true
pm2 delete wschat-backend || true
cd /opt/ws-chat/source/backend
pm2 start src/server.js --name wschat-backend --update-env
pm2 save
sleep 5
curl -s http://127.0.0.1:3000/health | jq
```
If 409 persists:
```bash
ps aux | grep -E "node|server.js|wschat" | grep -v grep
```
Only one polling instance may run per Telegram bot token.
## Important recent commits
```text
4b46aabc8210158f97c3c6e9274b8f703f7a8aa2 - Telegram proxy changed to socks5h
6f14353cd403f351c89e4274d189808951dcf940 - production DB fallback fixed
be004fd14ab16e3b1262980fe044356d2efbe806 - health endpoint includes dbPath
```
## Deployment commands
Backend update:
```bash
cd /opt/ws-chat/source
git pull --ff-only origin main
cd backend
npm install
pm2 restart wschat-backend --update-env
```
Hard restart as single PM2 process:
```bash
pkill -f "/opt/ws-chat/source/backend/src/server.js" || true
pkill -f "node src/server.js" || true
pm2 delete wschat-backend || true
cd /opt/ws-chat/source/backend
npm install
pm2 start src/server.js --name wschat-backend --update-env
pm2 save
```
Frontend build/publish:
```bash
cd /opt/ws-chat/source
npm install
npm run build
rsync -av --delete widget/dist/ /var/www/widget_stack_usr/data/www/widget.stackworks.ru/
rsync -av --delete admin-panel/dist/ /var/www/widget_stack_usr/data/www/widget.stackworks.ru/admin/
```
Health/logs:
```bash
curl -s http://127.0.0.1:3000/health | jq
pm2 logs wschat-backend --lines 100
```
## FastPanel safety rules
Never edit global FastPanel/nginx configs from project scripts. Never bind project services directly to ports 80/443. Never run `rsync --delete` against `/var/www` or parent directories. Copy static files only into exact domain webroots.
## Current next steps
1. Kill duplicate Telegram polling process.
2. Start exactly one PM2 process `wschat-backend`.
3. Confirm `/health`: correct `dbPath` and `telegram.running=true`.
4. Send `/start` to the Telegram bot.
5. Send widget message and confirm it reaches Telegram.
6. Implement Telegram reply delivery back to widget via WebSocket.
7. Add admin bridge status/restart button.
8. Add admin operator list.
9. Add admin auth.
10. Fix production widget build to emit stable `widget.js`.