forked from coldnight/pual_bot
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathmessage_dispatch.py
More file actions
234 lines (199 loc) · 8.79 KB
/
message_dispatch.py
File metadata and controls
234 lines (199 loc) · 8.79 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
#!/usr/bin/env python
# -*- coding:utf-8 -*-
#
# Copyright 2013 cold
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
#
# Author : cold
# E-mail : wh_linux@126.com
# Date : 13/03/01 11:44:05
# Desc : 消息调度
#
import re
import logging
from functools import partial
from command import Command
from config import MAX_RECEIVER_LENGTH
code_typs = ['actionscript', 'ada', 'apache', 'bash', 'c', 'c#', 'cpp',
'css', 'django', 'erlang', 'go', 'html', 'java', 'javascript',
'jsp', 'lighttpd', 'lua', 'matlab', 'mysql', 'nginx',
'objectivec', 'perl', 'php', 'python', 'python3', 'ruby',
'scheme', 'smalltalk', 'smarty', 'sql', 'sqlite3', 'squid',
'tcl', 'text', 'vb.net', 'vim', 'xml', 'yaml']
ABOUT_STR = u"Author : cold\nE-mail : wh_linux@126.com\n"\
u"HomePage : http://t.cn/zTocACq\n"\
u"Project@ : http://git.io/hWy9nQ"
HELP_DOC = u"http://paste.linuxzen.com/p/Mzcw/text"
u"""Pual 使用指南:
-tr <content> 可以对<content>进行英汉互译
```<type>\\n<code> 可以将<code>以<type>高亮的方式贴到http://paste.linuxzen.com
>>> <statement> 可以执行Python语句, 并为你个人将这个语句产生的定义放在服务器
ping Pual 可以查看Pual是否在线
about Pual 可以查看Pual相关信息
help Pual 显示本信息
"""
URL_RE = re.compile(r"(http[s]?://(?:[-a-zA-Z0-9_]+\.)+[a-zA-Z]+(?::\d+)"
"?(?:/[-a-zA-Z0-9_%./]+)*\??[-a-zA-Z0-9_&%=.]*)",
re.UNICODE)
class MessageDispatch(object):
""" 消息调度器 """
def __init__(self, webqq):
self.webqq = webqq
self.cmd = Command()
def send_msg(self, content, callback, nick = None):
self.cmd.send_msg(content, callback, nick)
def handle_qq_msg_contents(self, contents):
content = ""
for row in contents:
if isinstance(row, (str, unicode)):
content += row.replace(u"【提示:此用户正在使用Q+"
u" Web:http://web.qq.com/】", "")\
.replace(u"【提示:此用户正在使用Q+"
u" Web:http://web3.qq.com/】", "")
return content.replace("\r", "\n").replace("\r\n", "\n")\
.replace("\n\n", "\n")
def handle_qq_group_msg(self, message):
""" 处理组消息 """
value = message.get("value", {})
gcode = value.get("group_code")
uin = value.get("send_uin")
contents = value.get("content", [])
content = self.handle_qq_msg_contents(contents)
uname = self.webqq.get_group_member_nick(gcode, uin)
if content:
logging.info(u"Got Group Message {0} from {1}".format(content, gcode))
pre = u"{0}: ".format(uname)
callback = partial(self.webqq.send_group_msg, gcode)
self.handle_content(uin, content, callback, "g", pre)
def handle_qq_message(self, message, is_sess = False):
""" 处理QQ好友消息 """
value = message.get("value", {})
from_uin = value.get("from_uin")
contents = value.get("content", [])
content = self.handle_qq_msg_contents(contents)
if content:
typ = "Sess" if is_sess else "Friend"
logging.info(u"Got {0} Message {1} from {2}".format(typ, content, from_uin))
callback = self.webqq.send_sess_msg if is_sess else self.webqq.send_buddy_msg
callback = partial(callback, from_uin)
self.handle_content(from_uin, content, callback, "b")
def handle_content(self, from_uin, content, callback, typ = "g", pre = None):
""" 处理内容
Arguments:
`from_uin` - 发送者uin
`content` - 内容
`callback` - 仅仅接受内容参数的回调
`typ` - 消息类型 g 群消息 b 好友消息
`pre` - 处理后内容前缀
"""
send_msg = partial(self.send_msg, callback = callback, nick = pre)
content = content.strip()
urls = URL_RE.findall(content)
if urls:
logging.info(u"Get urls {0!r} from {1}".format(urls, content))
for url in urls:
self.cmd.url_info(url, send_msg)
if content.startswith("-py"):
body = content.lstrip("-py").strip()
self.cmd.py(body, send_msg)
return
if content.startswith("```"):
typ = content.split("\n")[0].lstrip("`").strip().lower()
if typ not in code_typs: typ = "text"
code = "\n".join(content.split("\n")[1:])
self.cmd.paste(code, send_msg, typ)
return
if typ == "g":
nickname = self.webqq.nickname.lower()
ping_cmd = "ping " + nickname
about_cmd = "about " + nickname
uptime_cmd = "uptime " + nickname
help_cmd = "help " + nickname
else:
ping_cmd = "ping"
about_cmd = "about"
uptime_cmd = "uptime"
help_cmd = "help"
commands = [ping_cmd, about_cmd, help_cmd, uptime_cmd]
command_resp = {ping_cmd:u"I am here ^_^", about_cmd:ABOUT_STR,
help_cmd:HELP_DOC, uptime_cmd : self.webqq.get_uptime()}
if content.strip().lower() in commands:
body = command_resp[content.strip().lower()]
if not isinstance(body, (str, unicode)):
body = body()
send_msg(body)
return
if content.startswith("-tr"):
if content.startswith("-trw"):
web = True
st = "-trw"
else:
web = False
st = "-tr"
body = content.lstrip(st).strip()
self.cmd.cetr(body, send_msg, web)
return
if content.startswith(">>>"):
body = content.lstrip(">").lstrip(" ")
self.cmd.shell(from_uin, body, send_msg)
return
if typ == "b":
if content.startswith(u"设置签名:") and content.count("|") == 1:
password, signature = content.strip(u"设置签名:").split("|")
self.webqq.set_signature(signature, password, send_msg)
return
if content:
self.cmd.simsimi(content, send_msg)
else:
send_msg(u"你总的说点什么吧")
return
if content.lower().startswith(self.webqq.nickname.lower()) \
or content.lower().endswith(self.webqq.nickname.lower()):
content = content.lower().strip(self.webqq.nickname.lower()).strip()
if content:
self.cmd.simsimi(content, send_msg)
else:
send_msg(u"你总的说点什么吧")
return
if u"提问的智慧" in content:
bodys = []
bodys.append(u"提问的智慧:")
bodys.append(u"原文: http://t.cn/hthAh")
bodys.append(u"译文: http://t.cn/SUHbCJ")
bodys.append(u"简化版: http://t.cn/hI2oe")
bodys.append(u"概括:")
bodys.append(u"1. 详细描述问题: 目的, 代码, 错误信息等")
bodys.append(u"2. 代码不要直接发到QQ上, 以免被替换成表情或丢失缩进")
bodys.append(u"3. 向帮你解决问题的人说谢谢 ")
callback("\n".join(bodys))
if len(content) > MAX_RECEIVER_LENGTH:
if pre:
cpre = u"{0}内容过长: ".format(pre)
else:
cpre = pre
send_pre_msg = partial(self.send_msg, callback = callback, nick = cpre)
self.cmd.paste(content, send_pre_msg)
def dispatch(self, qq_source):
if qq_source.get("retcode") == 0:
messages = qq_source.get("result")
for m in messages:
if m.get("poll_type") == "group_message":
self.handle_qq_group_msg(m)
if m.get("poll_type") == "message":
self.handle_qq_message(m)
if m.get("poll_type") == "kick_message":
self.webqq.stop()
if m.get("poll_type") == "sess_message":
self.handle_qq_message(m, True)