Skip to content

Commit

Permalink
1. Fix name issue in group chat.
Browse files Browse the repository at this point in the history
2. Unescape user name.
3. Extract @ infos of text messages in group chat.
  • Loading branch information
liuwons committed Mar 6, 2016
1 parent 776cae2 commit 7733739
Show file tree
Hide file tree
Showing 5 changed files with 239 additions and 95 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -68,3 +68,4 @@ target/
qr.png
/*.jpg
*.ini
*.un~
14 changes: 14 additions & 0 deletions CHANGES.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
# Change Log


# V0.1

时间: 2016-06-05

初始版本。

***wxbot.py*** 已经实现了基本的群聊、单聊接口。

***test.py*** 实现了一个功能最基础的机器人,对所有好友的文本消息回复 *hi* ,并不断向好友 *tb* 发送 *schedule*

***bot.py*** 利用 ***wxBot******图灵机器人*** 实现了一个群聊机器人。对好友以及群聊中@自己的消息进行回复。
35 changes: 26 additions & 9 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ Web微信协议参考资料:

## 1 环境与依赖

目前只能运行于Python 2环境 。
此版本只能运行于Python 2环境 。

**wxBot** 用到了Python **requests** , **pypng** , 以及 **pyqrcode** 库。

Expand All @@ -59,7 +59,7 @@ pip install pypng

以下的代码对所有来自好友的文本消息回复 *hi* , 并不断向好友 *tb* 发送 *schedule*

`handle_msg_all` 函数用于处理收到的每条消息,而 `schedule` 函数可以做一些任务性的事情(例如不断向好友推送信息或者一些定时任务)。
`handle_msg_all` 函数用于处理收到的每条消息,而 `schedule` 函数可以做一些任务性的工作(例如不断向好友推送信息或者一些定时任务)。

```python
#!/usr/bin/env python
Expand Down Expand Up @@ -97,7 +97,7 @@ python test.py

### 2.3 登录微信

程序运行之后,会在当前目录下生成二维码图片文件 ***qr.png*** ,用微信扫描此二维码并按操作指示确认登录网页微信。
程序运行之后,会在当前目录下生成二维码图片文件 ***qr.png*** 并自动打开,用微信扫描此二维码并按操作指示确认登录网页微信。

如果运行在Linux下,还可以通过设置 **WXBot** 对象的 `conf['qr']``tty` 的方式直接在终端打印二维码(此方法只能在Linux终端下使用),效果如下:

Expand Down Expand Up @@ -131,7 +131,7 @@ python test.py
| 0 | 初始化消息,内部数据 | 无意义,可以忽略 |
| 1 | 自己发送的消息 | 无意义,可以忽略 |
| 2 | 文件消息 | 字典,包含 `type``data` 字段 |
| 3 | 群消息 | 字典, 包含 `user` (字典,包含 `id``name`字段,都是字符串,表示发送此消息的群用户)与 `type``data` 字段,红包消息除外(只有 `type` 字段) |
| 3 | 群消息 | 字典, 包含 `user` (字典,包含 `id``name`字段,都是字符串,表示发送此消息的群用户)与 `type``data` 字段,红包消息只有 `type` 字段, 文本消息还有detail、desc字段, 参考 **群文本消息** |
| 4 | 联系人消息 | 字典,包含 `type``data` 字段 |
| 5 | 公众号消息 | 字典,包含 `type``data` 字段 |
| 6 | 特殊账号消息 | 字典,包含 `type``data` 字段 |
Expand All @@ -156,8 +156,21 @@ python test.py
| 12 | 红包 | 不可用 |
| 99 | 未知类型 | 不可用 |

### 4.4 群文本消息

### 4.4 WXBot对象属性
由于群文本消息中可能含有@信息,因此群文本消息的 `content` 字典除了含有 `type``data` 字段外,还含有 `detail``desc` 字段。

各字段内容为:

| 字段 | 内容 |
| --- | ---- |
| `type` | 数据类型, 为0(文本) |
| `data` | 字符串,消息内容,含有@信息 |
| `desc` | 字符串,删除了所有@信息 |
| `detail` | 数组,元素类型为含有 `type``value` 字段的字典, `type` 为字符串 ***str*** (表示元素为普通字符串,此时value为消息内容) 或 ***at*** (表示元素为@信息, 此时value为所@的用户名) |


### 4.5 WXBot对象属性

**WXBot** 对象在登录并初始化之后,含有以下的可用数据:

Expand All @@ -169,7 +182,7 @@ python test.py
| `special_list` | 特殊账号列表 |
| `session` | **WXBot** 与WEB微信服务器端交互所用的 **Requests** `Session` 对象 |

### 4.5 WXBot对象方法
### 4.6 WXBot对象方法

**WXBot** 对象还含有一些可以利用的方法

Expand All @@ -179,14 +192,14 @@ python test.py
| `get_head_img(id)` | 获取用户头像并保存到本地文件 ***img_[id].jpg***`id` 为用户id(Web微信数据) |
| `get_msg_img(msgid)` | 获取图像消息并保存到本地文件 ***img_[msgid].jpg*** , `msgid` 为消息id(Web微信数据) |
| `get_voice(msgid)` | 获取语音消息并保存到本地文件 ***voice_[msgid].mp3*** , `msgid` 为消息id(Web微信数据) |
| `get_account_name(uid)` | 获取微信id对应的名称,返回一个可能包含 `remark_name` (备注名), `nickname` (昵称), `display_name` (群名称)的字典|
| `get_contact_name(uid)` | 获取微信id对应的名称,返回一个可能包含 `remark_name` (备注名), `nickname` (昵称), `display_name` (群名称)的字典|
| `send_msg_by_uid(word, dst)` | 向好友发送消息,`word` 为消息字符串,`dst` 为好友用户id(Web微信数据) |
| `send_msg(name, word, isfile)` | 向好友发送消息,`name` 为好友的备注名或者好友微信号, `isfile``False``word` 为消息,`isfile``True``word` 为文件路径(此时向好友发送文件里的每一行) |
| `send_msg(name, word, isfile)` | 向好友发送消息,`name` 为好友的备注名或者好友微信号, `isfile``False``word` 为消息,`isfile``True``word` 为文件路径(此时向好友发送文件里的每一行),此方法在有重名好友时会有问题,因此更推荐使用 `send_msg_by_uid(word, dst)` |
| `is_contact(uid)` | 判断id为 `uid` 的账号是否是本帐号的好友,返回 `True` (是)或 `False` (不是) |
| `is_public(uid)` | 判断id为 `uid` 的账号是否是本帐号所关注的公众号,返回 `True` (是)或 `False` (不是) |


## 5 Example
## 5 群聊机器人示例

***bot.py*****[图灵机器人](http://www.tuling123.com/)** API 以及 **wxBot** 实现了一个自动回复机器人.

Expand Down Expand Up @@ -230,3 +243,7 @@ python test.py
```python
python bot.py
```
## 6 帮助项目
欢迎对本项目提意见、贡献代码,参考: [如何帮助项目](https://github.com/liuwons/wxBot/wiki/How-to-contribute)
63 changes: 25 additions & 38 deletions bot.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,15 +43,15 @@ def tuling_auto_reply(self, uid, msg):

def auto_switch(self, msg):
msg_data = msg['content']['data']
STOP = [u'退下', u'走开', u'关闭', u'关掉', u'休息', u'滚开']
START = [u'出来', u'启动', u'工作']
stop_cmd = [u'退下', u'走开', u'关闭', u'关掉', u'休息', u'滚开']
start_cmd = [u'出来', u'启动', u'工作']
if self.robot_switch:
for i in STOP:
for i in stop_cmd:
if i == msg_data:
self.robot_switch = False
self.send_msg_by_uid(u'[Robot]' + u'机器人已关闭!', msg['to_user_id'])
else:
for i in START:
for i in start_cmd:
if i == msg_data:
self.robot_switch = True
self.send_msg_by_uid(u'[Robot]' + u'机器人已开启!', msg['to_user_id'])
Expand All @@ -63,44 +63,31 @@ def handle_msg_all(self, msg):
self.auto_switch(msg)
elif msg['msg_type_id'] == 4 and msg['content']['type'] == 0: # text message from contact
self.send_msg_by_uid(self.tuling_auto_reply(msg['user']['id'], msg['content']['data']), msg['user']['id'])
elif msg['msg_type_id'] == 3: # group message
if msg['content']['data'].find('@') >= 0: # someone @ another
my_names = self.get_group_member_name(msg['user']['id'], self.user['UserName'])
elif msg['msg_type_id'] == 3 and msg['content']['type'] == 0: # group text message
if 'detail' in msg['content']:
my_names = self.get_group_member_name(self.my_account['UserName'], msg['user']['id'])
if my_names is None:
my_names = {}
if 'NickName' in self.user and len(self.user['NickName']) > 0:
my_names['nickname2'] = self.user['NickName']
if 'RemarkName' in self.user and len(self.user['RemarkName']) > 0:
my_names['remark_name2'] = self.user['RemarkName']
if 'NickName' in self.my_account and self.my_account['NickName']:
my_names['nickname2'] = self.my_account['NickName']
if 'RemarkName' in self.my_account and self.my_account['RemarkName']:
my_names['remark_name2'] = self.my_account['RemarkName']

is_at_me = False
text_msg = ''
for _ in my_names:
if msg['content']['data'].find('@'+my_names[_]) >= 0:
is_at_me = True
text_msg = msg['content']['data'].replace('@'+my_names[_], '').strip()
break
if is_at_me: # someone @ me
snames = self.get_group_member_name(msg['user']['id'], msg['content']['user']['id'])
if snames is None:
snames = self.get_account_name(msg['content']['user']['id'])
src_name = ''
if snames is not None:
if 'display_name' in snames and len(snames['display_name']) > 0:
src_name = snames['display_name']
elif 'nickname' in snames and len(snames['nickname']) > 0:
src_name = snames['nickname']
elif 'remark_name' in snames and len(snames['remark_name']) > 0:
src_name = snames['remark_name']
for detail in msg['content']['detail']:
if detail['type'] == 'at':
for k in my_names:
if my_names[k] and my_names[k] == detail['value']:
is_at_me = True
break
if is_at_me:
src_name = msg['content']['user']['name']
reply = 'to ' + src_name + ': '
if msg['content']['type'] == 0: # text message
reply += self.tuling_auto_reply(msg['content']['user']['id'], msg['content']['desc'])
else:
return

if src_name != '':
reply = '@' + src_name + ' '
if msg['content']['type'] == 0: # text message
reply += self.tuling_auto_reply(msg['content']['user']['id'], text_msg)
else:
reply += u"对不起,只认字,其他杂七杂八的我都不认识,,,Ծ‸Ծ,,"
self.send_msg_by_uid(reply, msg['user']['id'])
reply += u"对不起,只认字,其他杂七杂八的我都不认识,,,Ծ‸Ծ,,"
self.send_msg_by_uid(reply, msg['user']['id'])


def main():
Expand Down
Loading

0 comments on commit 7733739

Please sign in to comment.