# Tao Cmt

> This skill should be used when the user asks to "tạo cmt", "viết comment cho bài forum", "viết cmt seeding", "chạy sheet cmt forum", "/tao-cmt [URL sheet]", "điền cột Nội dung cmt", or gives a Google Sheet tracking forum posts that need seeding comments. Reads each forum post URL from the sheet, writes one natural Vietnamese forum-style comment per row that contains the row's product keyword, the brand name, and the row's target link, then writes the comments back into the sheet's comment column — only for rows whose comment cell is still empty.

- Skill: `nguyenminhnguyet-ops/tao-cmt` (Agent Skill, multi-file: 4 files)
- Install (CLI): `npx skillmds@latest add nguyenminhnguyet-ops/tao-cmt`
- Raw SKILL.md: https://api.skillmd.com/api/skills/nguyenminhnguyet-ops/tao-cmt/raw
- Safety review: pending (external: skill-scanner PASS, skillspector CAUTION)
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Coding & Dev Tools
- Author: nguyenminhnguyet-ops (https://skillmd.com/u/nguyenminhnguyet-ops)
- Updated: 2026-09-22
- Page: https://skillmd.com/skills/nguyenminhnguyet-ops/tao-cmt

---


# tao-cmt

Viết comment seeding cho các bài forum được theo dõi trong 1 Google Sheet. Với mỗi dòng có URL bài nhưng ô "Nội dung cmt" còn trống: đọc bài gốc, viết 1 comment giọng người dùng thật, có chứa từ khoá sản phẩm + tên thương hiệu + link đích của dòng đó, rồi ghi ngược vào sheet.

## Khi nào dùng

- User đưa link 1 sheet theo dõi cmt forum và bảo "viết cmt cho các dòng chưa có".
- User gõ `/tao-cmt` (có thể kèm URL sheet).

KHÔNG dùng skill này khi:

- User muốn viết nguyên 1 bài forum mới → skill `viet-bai-forum`.
- User muốn đăng bài lên nền tảng → các skill `share-bai-*`.
- Skill này KHÔNG tự đăng comment lên forum — chỉ soạn nội dung và điền vào sheet. Việc đăng do người phụ trách account làm thủ công (cột "Acc cmt").

## Tiền điều kiện

- [ ] Sheet đích đã có entry trong `../google-sheets-social/sheets-accounts.local.json` (skill này dùng chung OAuth/credential của skill `google-sheets-social`, KHÔNG tạo OAuth client riêng). Chưa có → chạy skill `google-sheets-social` để setup trước.
- [ ] Mọi HTTP đi qua `scripts/cmt-http.sh`, mọi xử lý dữ liệu đi qua `scripts/cmt-json.js`.

## Default settings

| Setting | Default | Override khi |
|---|---|---|
| Sheet-key | `<sheet-key-cua-ban>` (spreadsheet do bạn tự cấu hình trong `sheets-accounts.local.json`) | User đưa spreadsheet khác |
| Tab | `Thống kê cmt forum` (hoặc tên tab bạn dùng) | User chỉ định gid/tên tab khác — dùng `sheets-tabs` để map gid → tên tab |
| Bố cục cột | header dòng **2**, dữ liệu từ dòng **3**; **B** = URL bài cmt, **C** = SP (từ khoá), **D** = URL chèn link, **E** = Nội dung cmt | Sheet khác → đọc header rồi xác nhận với user |
| Thương hiệu bắt buộc nhắc trong cmt | `<tên thương hiệu của bạn>` | User nói brand khác |
| Độ dài cmt | 60–85 từ (3–4 câu) | User yêu cầu dài/ngắn hơn |

## Pipeline — 5 bước

### Step 1 — Xác định sheet + tab + bố cục cột

Parse `spreadsheet_id` từ URL. Lấy access token rồi map `gid` sang tên tab thật:

```
bash scripts/cmt-http.sh sheets-refresh-token <sheet-key> <scratch>/tok.json
bash scripts/cmt-http.sh sheets-tabs <sheet-key> <scratch>/tabs.json
```

Đọc tab, xác nhận dòng header và 4 cột (URL bài / từ khoá / link đích / nội dung cmt). Header của sheet mẫu nằm ở **dòng 2**, không phải dòng 1 — luôn kiểm tra bằng mắt trước khi chạy tiếp.

**Exit condition**: biết chắc `<tab-name>`, `<header-row>`, và 4 chữ cái cột.

### Step 2 — Lọc các dòng cần viết

```
bash scripts/cmt-http.sh sheets-get <sheet-key> "<tab-name>" <scratch>/sheet.json
node scripts/cmt-json.js parse-rows <scratch>/sheet.json <header-row> B C D E <scratch>/todo.json
```

Chỉ lấy dòng **có URL ở cột B** và **ô cột E còn trống**. Báo user số dòng cần viết trước khi chạy tiếp.

**Exit condition**: `todo.json` có danh sách `{row, url, keyword, target}`. Rỗng → báo "không có dòng nào cần viết", dừng.

### Step 3 — Đọc nội dung từng bài forum

```
bash scripts/cmt-http.sh fetch-post "<url>" <scratch>/p<row>.html
node scripts/cmt-json.js extract-post <scratch>/p<row>.html 3500
```

Tải song song nhiều bài một lượt (vòng lặp bash) cho nhanh, rồi extract từng bài để đọc.

**Exit condition**: đọc được TITLE + BODY của mọi dòng. HTTP 403/404 hoặc BODY rỗng → xem "Recovery".

### Step 4 — Viết comment

Đọc `references/comment-guidelines.md` trước khi viết. Với mỗi dòng, viết 1 comment bám đúng nội dung bài vừa đọc, ghi vào 1 file JSON dạng:

```json
[{"row":142,"keyword":"iPhone Duo","target":"https://...","comment":"..."}]
```

Tự kiểm tra trước khi ghi sheet:

```
node scripts/cmt-json.js check-comments <scratch>/cmts.json "<Tên thương hiệu của bạn>"
```

**Exit condition**: `check-comments` báo "Tất cả cmt đạt yêu cầu". Còn dòng FAIL → sửa comment đó rồi chạy lại, TUYỆT ĐỐI không ghi sheet khi còn FAIL.

### Step 5 — Ghi về sheet

Các dòng liên tiếp gộp 1 lần ghi:

```
node scripts/cmt-json.js build-column-payload <scratch>/cmts.json <scratch>/payload.json
bash scripts/cmt-http.sh sheets-write-column <sheet-key> "'<tab-name>'!E<first>:E<last>" <scratch>/payload.json <scratch>/wr.json
node scripts/cmt-json.js show-update-result <scratch>/wr.json
```

`build-column-payload` tự chặn nếu danh sách dòng không liên tiếp — khi đó tách thành nhiều lần ghi theo từng cụm liên tiếp.

Verify: chạy lại Step 2, số "cần viết" phải giảm đúng bằng số cmt vừa ghi.

**Exit condition**: `updatedCells` khớp số dòng, verify sạch.

## Decision points

| Step | Hỏi user khi | Auto-proceed khi |
|---|---|---|
| 1 | Không map được gid → tab, hoặc header/cột không giống default | Sheet quen thuộc, bố cục khớp default |
| 2 | Số dòng cần viết > 30 (xác nhận trước khi tốn thời gian) | ≤ 30 dòng |
| 3 | Bài bị chặn/không đọc được nội dung | Đọc được TITLE + BODY |
| 4 | Từ khoá cột C trống, hoặc link cột D trống | Đủ cả 2 |
| 5 | Ô cột E đã có nội dung (không ghi đè) | Ô trống |

## Recovery

- `fetch-post` trả **403** → hầu hết forum VN chặn user-agent lạ; script đã gửi UA trình duyệt. Vẫn 403 → thử lại 1 lần, vẫn hỏng thì bỏ qua dòng đó, báo user, KHÔNG bịa nội dung bài.
- `extract-post` cho BODY quá ngắn (< 200 ký tự) → bài có thể chỉ là ảnh hoặc dùng layout khác. Đọc phần DESC/COMMENTS để nắm ý, nếu vẫn không đủ thì bỏ qua dòng, báo user.
- Cột C (từ khoá) trống → hỏi user lấy từ khoá ở đâu, KHÔNG tự suy từ tiêu đề bài.
- `sheets-write-column` lỗi 401/403 → access token hết hạn, chạy lại `sheets-refresh-token` rồi ghi lại.
- Lỗi range → kiểm tra tên tab đã bọc dấu nháy đơn `'Thống kê cmt forum'!E142:E151` chưa.

## Output format

```
Sheet: <tên tab> — <N> dòng có URL, <M> đã có cmt, <K> cần viết.
Đã viết & ghi <K> comment vào cột E (dòng <first>–<last>).

| Dòng | Bài | Từ khoá | Link chèn |
|---|---|---|---|
| 142 | <tiêu đề rút gọn> | iPhone Duo | abcstore.vn/... |
...

Bỏ qua: <dòng + lý do>  (chỉ in khi có)
```

Kèm 1–2 câu nói rõ: comment mới nằm trong sheet, CHƯA được đăng lên forum.

## Anti-patterns

- KHÔNG viết cmt khi chưa đọc bài gốc — comment chung chung kiểu "bài hay quá bác" bị forum xoá và không có giá trị SEO.
- KHÔNG ghi đè ô cột E đã có nội dung.
- KHÔNG dùng từ xếp hạng tuyệt đối ("tốt nhất", "số 1", "hàng đầu") hay giọng quảng cáo lộ liễu — cmt phải giống người dùng thật đang bàn luận.
- KHÔNG gắn nhiều hơn 1 link trong một comment.
- KHÔNG dùng cùng một mẫu câu cho nhiều dòng — nhiều dòng có thể trỏ về cùng 1 bài, mỗi cmt phải khai thác một góc khác nhau của bài.
- KHÔNG tự đăng comment lên forum — ngoài phạm vi skill.
- KHÔNG tạo OAuth client mới; dùng lại credential của `google-sheets-social` (Google giới hạn 50 refresh_token/cặp client-tài khoản).

## Skill files

| File | Purpose | Load when |
|---|---|---|
| `references/comment-guidelines.md` | Công thức viết 1 comment tự nhiên: cấu trúc 3–4 câu, cách chèn từ khoá + link, giọng điệu, ví dụ đạt/không đạt | Step 4 |
| `scripts/cmt-http.sh` | Mọi HTTP: tải bài forum (UA trình duyệt), và proxy đọc/ghi Google Sheets | Step 1, 2, 3, 5 |
| `scripts/cmt-json.js` | Mọi xử lý dữ liệu: lọc dòng cần viết, bóc nội dung bài từ HTML, tự kiểm tra cmt, dựng payload ghi sheet | Step 2, 3, 4, 5 |

