{"id":28445048,"url":"https://github.com/wechaty/ha","last_synced_at":"2025-06-29T20:33:00.972Z","repository":{"id":47139971,"uuid":"253416595","full_name":"wechaty/ha","owner":"wechaty","description":"High Available (HA) Wechaty is a Load Balance for providing High Availability for Wechaty Chatbot by spreading requests across multiple WeChat individual accounts.","archived":false,"fork":false,"pushed_at":"2021-11-19T13:33:49.000Z","size":407,"stargazers_count":4,"open_issues_count":8,"forks_count":1,"subscribers_count":3,"default_branch":"main","last_synced_at":"2025-06-04T04:01:34.967Z","etag":null,"topics":["chatbot","high-availability","wechaty"],"latest_commit_sha":null,"homepage":"https://npmjs.com/package/ha-wechaty","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/wechaty.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2020-04-06T06:44:15.000Z","updated_at":"2023-12-07T02:04:17.000Z","dependencies_parsed_at":"2022-08-25T02:41:47.686Z","dependency_job_id":null,"html_url":"https://github.com/wechaty/ha","commit_stats":null,"previous_names":["wechaty/ha-wechaty"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/wechaty/ha","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/wechaty%2Fha","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/wechaty%2Fha/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/wechaty%2Fha/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/wechaty%2Fha/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/wechaty","download_url":"https://codeload.github.com/wechaty/ha/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/wechaty%2Fha/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":262663350,"owners_count":23345035,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["chatbot","high-availability","wechaty"],"created_at":"2025-06-06T10:11:11.298Z","updated_at":"2025-06-29T20:33:00.946Z","avatar_url":"https://github.com/wechaty.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# High Available (HA) Wechaty\n\n[![NPM Version](https://img.shields.io/npm/v/ha-wechaty?color=brightgreen)](https://www.npmjs.com/package/ha-wechaty)\n[![NPM](https://github.com/wechaty/ha-wechaty/workflows/NPM/badge.svg)](https://github.com/wechaty/ha-wechaty/actions?query=workflow%3ANPM)\n[![ES Modules](https://img.shields.io/badge/ES-Modules-brightgreen)](https://github.com/Chatie/tsconfig/issues/16)\n\n![HAWechaty](https://wechaty.github.io/ha-wechaty/images/ha-wechaty.png)\n\n\u003c!-- markdownlint-disable MD013 --\u003e\nHA Wechaty is a Load Balance for providing High Availability for Wechaty Chatbot by spreading requests across multiple WeChat individual accounts.\n\n[![Powered by Wechaty](https://img.shields.io/badge/Powered%20By-Wechaty-brightgreen.svg)](https://github.com/Wechaty/wechaty)\n[![Powered by Ducks](https://img.shields.io/badge/Powered%20by-Ducks-yellowgreen)](https://github.com/huan/ducks#3-ducksify-extension-currying--ducksify-interface)\n\nOne two three, chatbots team up!\n\n## Background\n\nHow to delivering high levels of [SLA uptime](https://www.vxchnge.com/blog/uptime-statistics-impact-business)?\n\n### The Problem of Single Point Of Failure (SPOF)\n\nWe have serval issues when we providing a Chatbot service, like:\n\n1. Single Point Of Failure (SPOF)\n1. Heartbeat \u0026 Keepalive\n\n### 1 Single Point Of Failure (SPOF)\n\n#### The Problem #1\n\nCurrently we have only one bot on WeChat, which means that if the bot was offline, then our service will be stopped.\n\n#### The Solution #1\n\nUse two (3 or even 4 will be better) WeChat bot at the same time, with the different wechaty-puppet providers (for example: padlocal + windows).\n\nSo when an issue event has come, we can use a RR (round robin) or other very easy to implementing algorithm to make our service both load-balancable and high-available.\n\n### 2 Heartbeat and Keepalive\n\n1. [Heartbeat](https://en.wikipedia.org/wiki/Heartbeat_(computing))\n1. [Keepalive](https://en.wikipedia.org/wiki/Keepalive)\n\n#### The Problem #2\n\nWhen a Wechaty bot is started and logged in, it is mostly liked to be work as expected for sending/receiving messages.\n\nHowever, sometimes it might run into trouble for some unknown reason, which caused it can not work anymore, but we have nothing to know about that.\n\nIn order to check whether a Wechaty bot is available, we need to take a test on it to see if it can send \u0026 receive the message successfully.\n\nHow can archive that? It is not a good idea if we send a message to another Wechaty bot because it is not stable enough for this kind of online service.\n\n#### The Solution #2\n\nWe can set up an Official Account for WeChat, with an auto-responding strategy that will reply a `dong` when it receives a `ding`.\n\nSo we let our Chatie Official Account takes the responsibility to provide this service.\n\n## HAProxy Requirement\n\n![QR Code for ChatieIO WeChat Official Account](docs/images/qrcode_for_gh_051c89260e5d_258.jpg)\n\nIf you want to use HAProxy, please make sure every bot account has followed the `ChatieIO` WeChat Official Account by scanning the above QR Code.\n\n## Usage\n\n```ts\nimport { HAWechaty } from 'ha-wechaty'\nimport { Wechaty } from 'wechaty'\n\nconst wechaty1 = new Wechaty({\n  puppet: 'wechaty-puppet-service',\n  puppetOptions: {\n    token: 'puppet-service-token'\n  }\n})\n\nconst wechaty2 = new Wechaty({\n  puppet: 'wechaty-puppet-padlocal',\n  puppetOptions: {\n    token: 'padlocal-token'\n  }\n})\n\n// 1. Configure HAWechaty\nconst haWechaty = configureHa()\n// 2. Add Wechaty instances to HA\nhaWechaty.add(wechaty1, wechaty2)\n// 3. Start HA\nawait haWechaty.start()\n\n// 4. Find room by our bots\nconst room = await haWechaty.Room.find({ topic: 'ding room' })\nif (room) {\n  // 5. Send message to room with load balancing and high availabilities\n  await room.say('ding')\n}\n```\n\n## Environment Variables\n\n### 1 `HA_WECHATY_PUPPET`\n\nThe wechaty puppet list, seprated by a colon (`:`).\n\nExamples:\n\n```sh\nexport HA_WECHATY_PUPPET=wechaty-puppet-service:wechaty-puppet-padlocal\n```\n\n### 2 `HA_WECHATY_PUPPET_TOKEN`\n\nWechaty Puppet Service Tokens that required by the puppets.\n\nThis is a token list, seprated by a colon (`:`), map to each puppet from `HA_WECHATY_PUPPET`.\n\n\u003e Leave it empty if a puppet does not require a token.\n\nThe token set to this environment variable will become the default value of `puppetOptions.token` when instantiating Wechaty.\n\nTo specify more tokens for a specific puppet, use a colon (`:`) to separate them, for example:\n\n```sh\nexport HA_WECHATY_PUPPET_TOKEN=token_1:token_2\n```\n\n## Development\n\n### Redux Remote DevTools\n\n```sh\nnpm run redux-devtools\n```\n\n## Links\n\n### Backoff Alghorithm\n\nSee issue: Backoff straitegy [#2](https://github.com/wechaty/ha-wechaty/issues/2)\n\n1. [Googl Cloud - Truncated exponential backoff](https://cloud.google.com/storage/docs/exponential-backoff)\n1. [Power of RxJS when using exponential backoff](https://medium.com/angular-in-depth/power-of-rxjs-when-using-exponential-backoff-a4b8bde276b0)\n1. [GRPC Connection Backoff Protocol](https://github.com/grpc/grpc/blob/master/doc/connection-backoff.md)\n\n### Redux\n\n1. [Redux Best Practices](https://medium.com/@kylpo/redux-best-practices-eef55a20cc72#.e8gil0ncl)\n1. [Typesafe utilities for \"action-creators\" in Redux / Flux Architecture](https://github.com/piotrwitek/typesafe-actions)\n1. [createAsyncEpic - Generic redux-observable factory handling async-actions - #162](https://github.com/piotrwitek/typesafe-actions/issues/162)\n\n### RxJS Testing\n\n1. [A better approach for testing your Redux code](https://blog.henriquebarcelos.dev/a-better-approach-for-testing-your-redux-code-ck3dnpqnu00uro4s178b8aw3e)\n1. [Marble testing with RxJS testing utils - You don’t need a third-party library for marble testing](https://medium.com/@kevinkreuzer/marble-testing-with-rxjs-testing-utils-3ae36ac3346a)\n1. [Testing RxJS Code with Marble Diagrams](https://github.com/ReactiveX/rxjs/blob/6.5.4/docs_app/content/guide/testing/marble-testing.md)\n1. [Extensive introduction to why and how you might want to use and test redux-observable](https://9oelm.github.io/2020-01-24--Fundamental-yet-extensive-introduction-to-why-and-how-you-might-want-to-use-redux-observable-for-async-actions/)\n1. [Writing Better Marble Tests for Redux Observable and TypeScript](https://itnext.io/better-marble-test-70c7676a1e2)\n\n### RxJS Operators\n\n1. [RxJS recipes: ‘forkJoin’ with the progress of completion for bulk network requests in Angular](https://indepth.dev/forkjoin-with-the-progress-of-completion-for-bulk-network-requests-in-angular/)\n1. [Handle multiple API requests in Angular using mergeMap and forkJoin to avoid nested subscriptions](https://levelup.gitconnected.com/handle-multiple-api-requests-in-angular-using-mergemap-and-forkjoin-to-avoid-nested-subscriptions-a20fb5040d0c)\n1. [Fun with RxJS's groupBy](dataquarium.io/blog/fun-with-rxjs-groupby/)\n1. [Here is what I’ve learn about groupBy operator by reading RxJS sources](https://medium.com/angular-in-depth/those-hidden-gotchas-within-rxjs-7d5c57406041)\n\n## History\n\n### master v0.9 (Sep 12, 2021)\n\n1. ES Modules supported\n  \n### v0.7 (Jun 4, 2021)\n\n#### BREAKING CHANGE\n\n1. Change `HA_WECHATY_PUPPET_`~~${PROTOCOL}_~~`TOKEN` to `HA_WECHATY_PUPPET_TOKEN` for easy understanding and prevent mis-configuration.\n\n### v0.4 (Jun 7, 2020)\n\n[![Ducksify Extension](https://img.shields.io/badge/Redux-Ducksify%202020-yellowgreen)](https://github.com/huan/ducks#3-ducksify-extension-currying--ducksify-interface)\n\n1. Work with [Ducks](https://github.com/huan/ducks)\n1. High-available logics managed by RxJS (redux-observable epics)\n1. Redux example at [examples/redux-ducks-bot/](examples/redux-ducks-bot/)\n1. Ding Dong Bot example at [examples/ding-dong-bot.ts](examples/ding-dong-bot.ts)\n\n### v0.0.1 (Apr 2020)\n\nThis module was originally design for the project [OSSChat](https://github.com/kaiyuanshe/osschat) [#58](https://github.com/kaiyuanshe/osschat/issues/58)\n\n1. Publish the NPM module [ha-wechaty](https://www.npmjs.com/package/ha-wechaty)\n\n## Author\n\n[Huan LI](https://github.com/huan) ([李卓桓](http://linkedin.com/in/zixia)) zixia@zixia.net\n\n[![Profile of Huan LI (李卓桓) on StackOverflow](https://stackexchange.com/users/flair/265499.png)](https://stackexchange.com/users/265499)\n\n## Copyright \u0026 License\n\n* Code \u0026 Docs © 2020 Huan LI \\\u003czixia@zixia.net\\\u003e\n* Code released under the Apache-2.0 License\n* Docs released under Creative Commons\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fwechaty%2Fha","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fwechaty%2Fha","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fwechaty%2Fha/lists"}