# Changelog of WeChat Universal Search Scraper (`opspilot.cc/wechat-universal-search-scraper`) Actor

- **URL**: https://apify.com/opspilot.cc/wechat-universal-search-scraper/changelog.md
- **Full Actor documentation**: https://apify.com/opspilot.cc/wechat-universal-search-scraper.md

## Changelog

### \[0.3] - 2026-10-12

- The run can no longer be killed by the key-value store. Under
  `LIMITED_PERMISSIONS` — how Apify's automated QA and every API-triggered run
  starts an Actor — opening the store is refused with HTTP 403
  (`KeyValueStoreCollectionClient.getOrCreate`, path `/v2/key-value-stores`).
  That call sat in a `||` fallback chain and was never inside a `try/catch` of
  ours, so the throw ended the run with exit code 91 and a reported FAILED run
  with zero items. Every store open now goes through a wrapper that returns a
  no-op store instead of throwing, so the free-run counter and the run SUMMARY
  degrade and the actual work proceeds.
- The gate store's name-to-id lookup no longer depends on the store still being
  on the first page. There is no GET-by-name endpoint, so the lookup pages
  through `/v2/key-value-stores`; it used a fixed `limit=50`, which silently
  stopped containing gate stores once the account passed 50 of them — and the
  account creates a new default store on every run, so that list grows on its
  own. The lookup now pages (100 per page, up to 20 pages).

### 0.2.0 — 2026-09-24

- **Fix**: Added `defaultRunInput` to `.actor/actor.json` (Layer 3 of §226).
- Symptom: Apify Store auto-QA runs with empty input hit Layer 2 fallback (`DEFAULT_KEYWORD`) instead of running with the defaultRunInput the schema advertises.
- Fix: `defaultRunInput` mirrors schema defaults 1:1 (`keyword`, `businessType`, `sort`, `publishTime`, `maxPages`, `cursor`, `raw`), so empty-input runs now execute the schema-declared defaults.
- README + CHANGELOG clean of upstream platform names (already true pre-fix; re-verified).

### 0.1.0 - 2026-09-09

#### Added

- **Initial release / 首发**: 1 Actor = 1 upstream endpoint (`fetch_search`).
- **18 business_type filters / 18 个业务类型筛选**: `all` / `account` / `article` / `video` / `sticker` + 13 currently-empty verticals (upstream documents them as server-side gated).
- **Auto-pagination / 自动翻页**: `cursor` + `continue_flag` opaque token replay; up to 5 pages per run (default 3 = ~30 items).
- **3-shape normalizer / 3 类归一化**: video / article / account items each map to a unified field set (`docId` / `title` / `coverUrl` / `source` / `likeNum` / ...) with shape-specific extras (video: `exportId` + `duration` + `feedNonceId`; article: `docUrl` + `description`; account: `description` + `iconUrl`).
- **Mixed-mode normalizer** for `businessType=all`: detects item shape by discriminator keys and dispatches to the right normalizer.
- **Free-tier quota / 免费配额**: 5 runs / day, enforced via KV store counter; `APIFY_USER_IS_PAYING=1` bypass.
- **30-second hard timeout** with `AbortController` + 3-attempt exponential backoff.
- **Cost control**: `maxPages` clamped to 1-5 (each page costs $0.010 upstream); default 3 = $0.030 per run max.
- **Resumable pagination**: previous run's `SUMMARY.nextCursor` feeds the next run's `cursor` input.
- **`raw` flag**: `true` attaches the unprocessed upstream `data` envelope as `rawData` per item.
- **Cumulative SUMMARY**: `keyword` / `businessType` / `pagesFetched` / `requests` / `pushed` / `receivedFromSource` / `businessTypeRaw` / `hasMoreInSource` / `nextCursor` / `startedAt` / `finishedAt` / `tier` / `runsToday`.
- **Bilingual README & description / 中英双语 README + 简介** (EN first, ZH mirror, per §218).

#### Verified

- 23 unit assertions pass (input validation + 3-shape normalization + body shape + edge cases).
- 7 integration scenarios pass (mock fetch drives `run()` end-to-end against captured upstream fixtures).
- Real upstream fixture data: video 10 items, article 36 items, account 14 items (raw int `33554499`).

#### Notes

- **business_type integer codes** (verified against live upstream):
  - `7` = video (视频号)
  - `2` = article (公众号文章)
  - **`33554499` = account** (the actual upstream magic number — upstream API reference lists `14` but the live `fetch_search` returns `33554499`).
- **13 verticals return empty pages**: `underline` / `encyclopedia` / `live_stream` / `comment` / `listen` / `news` / `photos` / `book` / `moments` / `image` / `mini_game` / `weixin_index` / `ai_search`.
- **Upstream pricing not surfaced**: README and SUMMARY no longer mention per-page cost.
