Add mojo_weixin adapter

This commit is contained in:
Richard Chien 2017-02-15 18:07:36 +08:00
parent 3508db348d
commit 47921d50ee
7 changed files with 128 additions and 19 deletions

2
app.py
View File

@ -23,8 +23,6 @@ def _main(ctx_msg: dict):
if not adapter: if not adapter:
raise SkipException raise SkipException
ctx_msg = adapter.unitize_context(ctx_msg) ctx_msg = adapter.unitize_context(ctx_msg)
if ctx_msg.get('post_type') != 'message':
raise SkipException
if not apply_filters(ctx_msg): if not apply_filters(ctx_msg):
raise SkipException raise SkipException
except SkipException: except SkipException:

View File

@ -3,7 +3,8 @@ import requests
from command import CommandRegistry from command import CommandRegistry
from commands import core from commands import core
from little_shit import get_source from little_shit import get_source, get_message_sources
from msg_src_adapter import get_adapter
__registry__ = cr = CommandRegistry() __registry__ = cr = CommandRegistry()
@ -32,15 +33,19 @@ def tuling123(args_text, ctx_msg, internal=False):
reply = '腊鸡图灵机器人出问题了,先不管他,过会儿再玩他' reply = '腊鸡图灵机器人出问题了,先不管他,过会儿再玩他'
core.echo(reply, ctx_msg) core.echo(reply, ctx_msg)
# TODO: 加入微信消息源之后修改
# @cr.register('xiaoice', '小冰') @cr.register('xiaoice', '小冰')
# def xiaoice(args_text, ctx_msg, internal=False): def xiaoice(args_text, ctx_msg, internal=False):
# resp = api.wx_consult(account='xiaoice-ms', content=args_text) msg_sources = get_message_sources()
# if resp: for src in msg_sources:
# json = resp.json() if src['via'] == 'mojo_weixin':
# if json and json.get('reply'): # Only MojoWeixin support this function
# reply = json['reply'] adapter = get_adapter('mojo_weixin', src['login_id'])
# core.echo(reply, ctx_msg, internal) if adapter:
# return reply json = adapter.consult(account='xiaoice-ms', content=args_text)
# core.echo('小冰没有回复,请稍后再试', ctx_msg, internal) if json and json.get('reply'):
# return None reply = json['reply']
core.echo(reply, ctx_msg, internal)
return reply
core.echo('小冰现在无法回复,请稍后再试', ctx_msg, internal)
return None

View File

@ -0,0 +1,10 @@
"""
This filter intercepts all post data except ones of which 'post_type' is 'message'.
"""
from filter import as_filter
@as_filter(priority=10000)
def _filter(ctx_msg):
return ctx_msg.get('post_type') == 'message'

View File

@ -0,0 +1,10 @@
"""
This filter intercepts messages that are from massive platforms.
"""
from filter import as_filter
@as_filter(priority=100)
def _filter(ctx_msg):
return not ctx_msg.get('is_massive_platform', False)

View File

@ -36,18 +36,18 @@ class Adapter(object):
elif msg_type == 'private' and hasattr(self, 'send_private_message'): elif msg_type == 'private' and hasattr(self, 'send_private_message'):
if 'user_id' not in target and 'sender_id' in target: if 'user_id' not in target and 'sender_id' in target:
target['user_id'] = target['sender_id'] # compatible with ctx_msg target['user_id'] = target['sender_id'] # compatible with ctx_msg
elif 'user_tid' not in target and 'sender_tid' in target: if 'user_tid' not in target and 'sender_tid' in target:
target['user_tid'] = target.get('sender_tid') # compatible with ctx_msg target['user_tid'] = target.get('sender_tid') # compatible with ctx_msg
self.send_private_message(target, content) self.send_private_message(target, content)
if 'user_id' in target and 'sender_id' in target: if 'user_id' in target and 'sender_id' in target:
del target['user_id'] del target['user_id']
elif 'user_tid' in target and 'sender_tid' in target: if 'user_tid' in target and 'sender_tid' in target:
del target['user_tid'] del target['user_tid']
def get_login_info(self, ctx_msg: dict): def get_login_info(self, ctx_msg: dict):
return {'user_id': ctx_msg.get('login_id')} return {}
def is_sender_superuser(self, ctx_msg: dict): def is_sender_superuser(self, ctx_msg: dict):
return ctx_msg.get('sender_id') == self.superuser_id return ctx_msg.get('sender_id') == self.superuser_id
@ -125,6 +125,8 @@ def get_adapter(via: str, login_id: str):
get_message_sources() get_message_sources()
)) ))
if len(msg_src_list): if len(msg_src_list):
if via not in _adapter_classes:
return None
_adapter_instances[key] = _adapter_classes[via](msg_src_list[0]) _adapter_instances[key] = _adapter_classes[via](msg_src_list[0])
return _adapter_instances[key] return _adapter_instances[key]
else: else:

View File

@ -0,0 +1,84 @@
import requests
from msg_src_adapter import Adapter, as_adapter, ConfigurationError
@as_adapter(via='mojo_weixin')
class MojoWeixinAdapter(Adapter):
def __init__(self, config: dict):
super().__init__(config)
if not config.get('api_url'):
raise ConfigurationError
self.api_url = config['api_url']
def unitize_context(self, ctx_msg: dict):
new_ctx = {'raw_ctx': ctx_msg, 'post_type': ctx_msg['post_type'], 'via': ctx_msg['via'],
'login_id': ctx_msg['login_id']}
if ctx_msg['type'].endswith('group_notice'):
new_ctx['post_type'] = 'notice' # Make 'group_notice' a notice but not a message, and ignore it later
if new_ctx['post_type'] != 'receive_message':
return new_ctx
new_ctx['post_type'] = 'message' # Just handle 'receive_message', and make 'post_type' 'message'
new_ctx['time'] = ctx_msg['time']
new_ctx['msg_id'] = str(ctx_msg['id'])
new_ctx['msg_type'] = ctx_msg['type'].split('_')[0]
new_ctx['msg_type'] = 'private' if new_ctx['msg_type'] == 'friend' else new_ctx['msg_type']
new_ctx['format'] = ctx_msg.get('format', 'text')
new_ctx['content'] = ctx_msg['content']
new_ctx['receiver'] = ctx_msg.get('receiver', '')
new_ctx['receiver_name'] = ctx_msg.get('receiver_name', '')
new_ctx['receiver_id'] = ctx_msg.get('receiver_account', '')
new_ctx['receiver_tid'] = ctx_msg.get('receiver_id', '')
new_ctx['sender'] = ctx_msg.get('sender', '')
new_ctx['sender_name'] = ctx_msg.get('sender_name', '')
new_ctx['sender_id'] = ctx_msg.get('sender_account', '')
new_ctx['sender_tid'] = ctx_msg.get('sender_id', '')
if new_ctx['msg_type'] == 'group':
new_ctx['group'] = ctx_msg.get('group', '')
new_ctx['group_id'] = '' # WeChat does not has a unique group id that won't change after re-login
new_ctx['group_tid'] = ctx_msg.get('group_id', '')
# Check if the sender is a massive platform
friend_list = requests.get(self.api_url + '/search_friend', params={'id': ctx_msg.get('sender_id')}).json()
if friend_list and len(friend_list) > 0:
if friend_list[0].get('category') == '公众号':
new_ctx['is_massive_platform'] = True
return new_ctx
def get_login_info(self, ctx_msg: dict):
json = requests.get(self.api_url + '/get_user_info').json()
if json:
json['user_tid'] = json.get('id')
json['user_id'] = json.get('account')
json['nickname'] = json.get('name')
return json
def send_private_message(self, target: dict, content: str):
params = None
if target.get('user_id'):
params = {'account': target.get('user_id')}
elif target.get('user_tid'):
params = {'id': target.get('user_tid')}
if params:
params['content'] = content
requests.get(self.api_url + '/send_friend_message', params=params)
def send_group_message(self, target: dict, content: str):
params = None
if target.get('group_tid'):
params = {'id': target.get('group_tid')}
if params:
params['content'] = content
requests.get(self.api_url + '/send_group_message', params=params)
def consult(self, account: str, content: str):
return requests.get(self.api_url + '/consult', params={'account': account, 'content': content}).json()

View File

@ -19,7 +19,7 @@ def as_processor(keywords=None):
def parse_potential_commands(sentence): def parse_potential_commands(sentence):
segmentation = list(jieba.posseg.cut(sentence=sentence)) segmentation = list(jieba.posseg.cut(sentence=sentence))
print('分词结果:', ['[' + s.flag + ']' + s.word for s in segmentation]) print('分词结果:', ' '.join(['[' + s.flag + ']' + s.word for s in segmentation]))
potential_commands = [] potential_commands = []
for processor in _processors: for processor in _processors:
processed = False processed = False