? Docker image | ? NPM package | ? FAQ
A small WeChat robot webhook helps you eliminate many obstacles to your own development. It is based on http requests. It is different from hooks WeChat. Because it is based on web api, the advantage is that it can be deployed on devices such as arm architecture.
Caution
The project is currently based on the web WeChat, which itself has the risk of being restricted. In addition, it is offline about once every two days. In addition to normal function repairs, it will not accept new feature requests. The windows protocol is under WIP and should be available to meet you in the near future!
Function | web protocol | windows protocol |
---|---|---|
Current availability | ✅ | |
code branch | main | windows |
Docker Tag | latest | windows |
<Send message> | ✅Single/Multiple/Group | ✅Single/Multiple/Group |
Send text | ✅ | ✅ |
Send pictures | ✅ Local image/url image analysis | ✅ Local image/url image analysis |
Send video (mp4) | ✅ Local video/url video analysis | |
Send documents | ✅ Local file/url file parsing | ✅ Local file/url file parsing |
<Receive message> | ||
receive text | ✅ | ✅ |
receive voice | ✅ | |
receive pictures | ✅ | |
receive video | ✅ | |
receive files | ✅ | |
Receive public account tweet link | ✅ | |
Receive system notifications | ✅ Online notification / offline notification / abnormal notification | |
Avatar acquisition | ✅ | |
Quick reply | ✅ | ✅ |
<Group management> | ||
<Friend Management> | ||
Receive friend request | ✅ | |
Request via friend | ✅ | |
Get contact list | ||
<Other functions> | ||
Automatic login without disconnection | ✅ | |
API authentication | ✅ | ✅ |
n8n seamless access | ✅ | |
Support docker deployment | ✅ arm64 / amd64 | ✅ amd64 |
Log file export | ✅ | ✅ |
The functions mentioned above have not been implemented yet. They are limited by WeChat protocol restrictions. Different protocols support different functions. Not all functions can be connected, for example:
npx wechatbot-webhook
Unless disconnected, the last login will be remembered by default. To change your account, please run the following command
npx wechatbot-webhook -r
If you encounter an installation error, please make sure your node version >= 18.14.1 #227
Copy the push message api from the command line, for example http://localhost:3001/webhook/msg/v2?token=[YOUR_PERSONAL_TOKEN]
Open a new terminal and try the following curl. Change the to and token field values to the values you want.
curl --location ' http://localhost:3001/webhook/msg/v2?token=[YOUR_PERSONAL_TOKEN] '
--header ' Content-Type: application/json '
--data ' { "to": "测试昵称", data: { "content": "Hello World!" }} '
Important
The package manager has been migrated to pnpm. Please use it to install dependencies to support some irregular temporary package patches and accelerate dependency installation.
docker pull dannicool/docker-wechatbot-webhook
# 启动容器并映射日志目录,日志按天维度生成,e.g: app.2024-01-01.log
docker run -d --name wxBotWebhook -p 3001:3001
-v ~ /wxBot_logs:/app/log
dannicool/docker-wechatbot-webhook
wget -O docker-compose.yml https://cdn.jsdelivr.net/gh/danni-cool/wechatbot-webhook@main/docker-compose.yml && docker-compose down && docker-compose -p wx_bot_webhook up
docker logs -f wxBotWebhook
Find the QR code login address, the url part below the picture, access it with a browser, scan the code to log in to wx
https://localhost:3001/login?token=[YOUR_PERSONAL_TOKEN]
Tips: You need to add parameters using -e, and separate multiple lines with , for example -e RECVD_MSG_API="https://example.com/your/url"
Function | variable | Remark |
---|---|---|
Log level | LOG_LEVEL=info | Log level, the default is info, only affects the current log output, consider using debug for detailed output. No matter how this value changes, the log file always records debug level logs. |
Receive message API | RECVD_MSG_API=https://example.com/your/url | If you want to handle the logic of receiving messages yourself, such as linking based on messages, fill in your processing logic URL |
Receive message API to accept messages sent by yourself | ACCEPT_RECVD_MSG_MYSELF=false | RECVD_MSG_API Whether to receive messages from itself (set to true, that is, received, default false) |
Custom login API token | LOGIN_API_TOKEN=abcdefg123 | You can also customize your own login token. If you do not configure it, one will be generated by default. |
Disable automatic login | DISABLE_AUTO_LOGIN=true | To kick out non-WeChat accounts, you can rely on the currently logged in session to avoid logging in . If you want to scan the QR code to log in every time, add this configuration. |
The v2 version interface adds a group sending function. For the v1 version interface, please move to legacy-api.
POST
application/json
payload
structureSend text or files to external links, and the external links will be parsed into pictures or files.
parameter | illustrate | data type | default value | Can it be empty | Optional parameters |
---|---|---|---|---|---|
to | For the message receiver , the incoming String will be sent to the nickname by default (the same applies to the group name). The incoming Object structure can be sent to the person who has made a note, for example: {alias: '备注名'} . The group name does not support the note name. | String Object | - | N | - |
isRoom | Whether to send a message to a group , this parameter determines whether you are looking for a group or a person when looking for someone, because the nickname is actually the same as the group name in terms of technical processing. | Boolean | false | Y | true false |
data | Message body structure, see payload.data below | Object Array | false | N | true false |
payload.data
structureparameter | illustrate | data type | default value | Can it be empty | Optional parameters |
---|---|---|---|---|---|
type | Message type , leave the field blank and parse to plain text | String text | - | Y | text fileUrl |
content | Message content , if you want to send multiple URLs and parse them, specify type as fileUrl. At the same time, fill in the URLs in content and separate them with English commas. | String | - | N | - |
curl --location ' http://localhost:3001/webhook/msg/v2?token=[YOUR_PERSONAL_TOKEN] '
--header ' Content-Type: application/json '
--data ' {
"to": "testUser",
"data": { "content": "你好" }
} '
In some cases, directly sending the url file name may not be what we want. The query parameter
$alias
can be used to splice the url to specify the file name sent to the target (note: aliases do not perform file conversion)
curl --location ' http://localhost:3001/webhook/msg/v2?token=[YOUR_PERSONAL_TOKEN] '
--header ' Content-Type: application/json '
--data ' {
"to": "testUser",
"data": {
"type": "fileUrl" ,
"content": "https://download.samplelib.com/jpeg/sample-clouds-400x300.jpg?$alias=cloud.jpg"
}
} '
curl --location ' http://localhost:3001/webhook/msg/v2?token=[YOUR_PERSONAL_TOKEN] '
--header ' Content-Type: application/json '
--data ' {
"to": "testGroup",
"isRoom": true,
"data": { "type": "fileUrl" , "content": "https://download.samplelib.com/jpeg/sample-clouds-400x300.jpg" },
} '
curl --location ' http://localhost:3001/webhook/msg/v2?token=[YOUR_PERSONAL_TOKEN] '
--header ' Content-Type: application/json '
--data ' {
"to": "testUser",
"data": [
{
"type": "text",
"content": "你好"
},
{
"type": "fileUrl",
"content": "https://samplelib.com/lib/preview/mp3/sample-3s.mp3"
}
]
} '
curl --location ' http://localhost:3001/webhook/msg/v2?token=[YOUR_PERSONAL_TOKEN] '
--header ' Content-Type: application/json '
--data ' [
{
"to": "testUser1",
"data": {
"content": "你好"
}
},
{
"to": "testUser2",
"data": [
{
"content": "你好"
},
{
"content": "近况如何?"
}
]
}
] '
response
structuresuccess
: Whether the message is sent successfully or not. Even if part of the group message is sent successfully, it will return true
message
: the message prompted when an error occurstask
: send task detailstask.successCount
: Number of successful messages senttask.totalCount
: total number of messagestask.failedCount
: Number of failed messages to sendtask.reject
: Parameters and error prompts due to failed parameter verificationtask.sentFailed
: Because sending failed and error prompttask.notFound
: Because the user or group is not found and error promptsEnsure the consistency of a single message sending. Failure to verify a certain parameter will terminate all message sending tasks.
{
"success" : true ,
"message" : " " ,
"task" : {
"successCount" : 0 ,
"totalCount" : 0 ,
"failedCount" : 0 ,
"reject" : [],
"sentFailed" : [],
"notFound" : []
}
}
Reading files currently only supports single sending.
POST
multipart/form-data
payload
structureparameter | illustrate | data type | default value | Can it be empty | Optional value |
---|---|---|---|---|---|
to | For the message receiver, the incoming String is sent to the nickname by default (the same applies to the group name). The incoming Json String structure supports sending to the person who has made a note, for example: --form 'to="{alias: "小号"}" ', the group name does not support comment names | String | - | N | - |
isRoom | Whether to send group messages , formData plain text can only use String type, 1 represents yes, 0 represents no, | String | 0 | Y | 1 0 |
content | File , local file can only be sent one at a time, multiple files are manually called multiple times | Binary | - | N | - |
curl --location --request POST ' http://localhost:3001/webhook/msg?token=[YOUR_PERSONAL_TOKEN] '
--form ' to=testGroup '
--form content=@ " $HOME /demo.jpg "
--form ' isRoom=1 '
response
structure {
"success" : true ,
"message" : " Message sent successfully "
}
payload
structurePOST
multipart/form-data
formData | illustrate | data type | Optional value | Example |
---|---|---|---|---|
type | Function type
Other types
System type
| String | text file urlLink friendship unknown system_event_login system_event_logout system_event_error system_event_push_notify | - |
content | The transferred content, text or transferred files share this field. Please see the example for structure mapping. | String Binary | Example | |
source | Message related sender data, JSON String | String | Example | |
isMentioned | The message is @mymessage #38 | String | 1 0 | - |
isMsgFromSelf | Is it a message from yourself #159 | String | 1 0 | - |
Server-side processing of formData generally requires corresponding handlers. Assuming that you have completed this step, you will get the following request
{
"type" : " text " ,
"content" : "你好" ,
"source" : " { " room " : "" , " to " :{ " _events " :{}, " _eventsCount " :0, " id " : " @f387910fa45 " , " payload " :{ " alias " : "" , " avatar " : " /cgi-bin/mmwebwx-bin/webwxgeticon?seq=1302335654&username=@f38bfd1e0567910fa45&skey=@crypaafc30 " , " friend " :false, " gender " :1, " id " : " @f38bfd1e10fa45 " , " name " : " ch. " , " phone " :[], " star " :false, " type " :1}}, " from " :{ " _events " :{}, " _eventsCount " :0, " id " : " @6b5111dcc269b6901fbb58 " , " payload " :{ " address " : "" , " alias " : "" , " avatar " : " /cgi-bin/mmwebwx-bin/webwxgeticon?seq=123234564&username=@6b5dbb58&skey=@crypt_ec356afc30 " , " city " : " Mars " , " friend " :false, " gender " :1, " id " : " @6b5dbd3facb58 " , " name " : " Daniel " , " phone " :[], " province " : " Earth " , " signature " : "" , " star " :false, " weixin " : "" , " type " :1}}} " ,
"isMentioned" : " 0 " ,
"isMsgFromSelf" : " 0 " ,
"isSystemEvent" : " 0 " // 考虑废弃,请使用type类型判断系统消息
}
Receive message api curl example (directly imported into postman for debugging)
curl --location 'https://your.recvdapi.com'
--form 'type="file"'
--form 'content=@"/Users/Downloads/13482835.jpeg"'
--form 'source="{\"room\":\"\",\"to\":{\"_events\":{},\"_eventsCount\":0,\"id\":\"@f387910fa45\",\"payload\":{\"alias\":\"\",\"avatar\":\"/cgi-bin/mmwebwx-bin/webwxgeticon?seq=1302335654&username=@f38bfd1e0567910fa45&skey=@crypaafc30\",\"friend\":false,\"gender\":1,\"id\":\"@f38bfd1e10fa45\",\"name\":\"ch.\",\"phone\":[],\"star\":false,\"type\":1}},\"from\":{\"_events\":{},\"_eventsCount\":0,\"id\":\"@6b5111dcc269b6901fbb58\",\"payload\":{\"address\":\"\",\"alias\":\"\",\"avatar\":\"/cgi-bin/mmwebwx-bin/webwxgeticon?seq=123234564&username=@6b5dbb58&skey=@crypt_ec356afc30\",\"city\":\"Mars\",\"friend\":false,\"gender\":1,\"id\":\"@6b5dbd3facb58\",\"name\":\"Daniel\",\"phone\":[],\"province\":\"Earth\",\"signature\":\"\",\"star\":false,\"weixin\":\"\",\"type\":1}}}"'
--form 'isMentioned="0"'
response
structure (optional)If you expect to reply immediately ( quick reply ) after receiving a message using
RECVD_MSG_API
, please return the return value according to the following structure. If there is no return value, the message will not be replied.
json
parameter | illustrate | data type | default value | Can it be empty | Optional parameters |
---|---|---|---|---|---|
success | Whether the request is successful or not, returns false or does not have this field, and the reply will not be processed. Some special messages are also controlled through this field, such as adding friend invitations. If true is returned, the friend request will be processed. | Boolean | - | Y | true false |
data | If you need to reply to a message, you need to define the data field | Object Object Array | - | Y |
response.data
structureparameter | illustrate | data type | default value | Can it be empty | Optional parameters |
---|---|---|---|---|---|
type | Message type . If this field is not filled in, it will default to text type transmission. | String | text | Y | text fileUrl |
content | Message content , if you want to send multiple URLs and parse them, specify type as fileUrl. At the same time, fill in the URLs in content and separate them with English commas. | String | - | N | - |
If you reply to a single message
{
"success" : true ,
"data" : {
"type" : " text " ,
"content" : " hello world! "
}
}
Combine replies to multiple messages
{
"success" : true ,
"data" : [
{
"type" : " text " ,
"content" : " hello world! "
},
{
"type" : " fileUrl " ,
"content" : " https://samplelib.com/lib/preview/mp3/sample-3s.mp3 "
}
]
}
In addition to configuring the token when docker starts, in the case of the default token, a default token will be generated by default and written to the
.env
file.
/login
GET
200
Return json containing the current user
{ "success" : true , "message" : " Contact<TestUser>is already login " }
Display WeChat login scan code page
You can actively poll the interface to check whether the service is running normally.
/healthz
GET
200
If WeChat is logged in, the plain text healthy
will be returned, otherwise unHealthy
will be returned.
Starting from version 2.8.0, you can access static resources such as avatars through this interface. For details, see the avatar field in the recvd_api data structure example.
Note that all static resource addresses reported to recvd_api will not have tokens by default and need to be spliced by yourself, otherwise a 401 error will be returned. Please ensure that you are logged in with WeChat and you need to obtain resources through the login state.
Address : /resouces
methods : GET
query :
/avatar/1234567890.jpg
encoded as avatar%2F1234567890.jpg
status : 200
404
401
example : http://localhost:3001/resouces?media=%2Fcgi-bin%2Fmmwebwx-bin%2Fwebwxgetheadimg%3Fseq%3D83460%26username%3D%40%4086815a%26skey%3D&token=[YOUR_PERSONAL_TOKEN]
200
Successfully obtain resources and return static resource files
404
Failed to obtain resources
401
does not carry login token { "success" : false , "message" : " Unauthorized: Access is denied due to invalid credentials. " }
401
WeChat login status has expired {
"success" : false , "message" : " you must login first "
}
Thanks to all our contributors!
See CHANGELOG for updated content