Skip to content

Commit

Permalink
embedding user profile
Browse files Browse the repository at this point in the history
  • Loading branch information
smn committed Apr 8, 2014
1 parent d171695 commit 8de6ce1
Show file tree
Hide file tree
Showing 2 changed files with 107 additions and 1 deletion.
62 changes: 62 additions & 0 deletions vumi/transports/wechat/tests/test_wechat.py
Original file line number Diff line number Diff line change
Expand Up @@ -549,3 +549,65 @@ def test_infer_news_message(self):
self.assertTrue(
'<Description> Go visit it.</Description>'
in resp.delivered_body)


class TestWeChatEmbedUserProfile(WeChatTestCase):

@inlineCallbacks
def test_embed_user_profile(self):
# NOTE: From http://admin.wechat.com/wiki/index.php?title=User_Profile
user_profile = {
"subscribe": 1,
"openid": "fromUser",
"nickname": "Band",
"sex": 1,
"language": "zh_CN",
"city": "Guangzhou",
"province": "Guangdong",
"country": "China",
"headimgurl": (
"http://wx.qlogo.cn/mmopen/g3MonUZtNHkdmzicIlibx6iaFqAc56v"
"xLSUfpb6n5WKSYVY0ChQKkiaJSgQ1dZuTOgvLLrhJbERQQ4eMsv84eavH"
"iaiceqxibJxCfHe/0"),
"subscribe_time": 1382694957
}

transport = yield self.get_transport_with_access_token(
'foo', embed_user_profile=True)
resp_d = request(
transport, 'POST', data="""
<xml>
<ToUserName><![CDATA[toUser]]></ToUserName>
<FromUserName><![CDATA[fromUser]]></FromUserName>
<CreateTime>1348831860</CreateTime>
<MsgType><![CDATA[text]]></MsgType>
<Content><![CDATA[this is a test]]></Content>
<MsgId>10234567890123456</MsgId>
</xml>
""".strip())

req = yield self.request_queue.get()
self.assertEqual(req.args, {
'access_token': ['foo'],
'lang': ['en'],
'openid': ['fromUser'],
})

req.write(json.dumps(user_profile))
req.finish()

[msg] = yield self.tx_helper.wait_for_dispatched_inbound(1)
yield self.tx_helper.make_dispatch_reply(msg, 'Bye!')

self.assertEqual(
msg['transport_metadata']['wechat']['UserProfile'],
user_profile)

up_key = transport.user_profile_key('fromUser')
cached_up = yield transport.redis.get(up_key)
config = transport.get_static_config()
self.assertEqual(json.loads(cached_up), user_profile)
self.assertTrue(0
< (yield transport.redis.ttl(up_key))
<= config.embed_user_profile_lifetime)
yield resp_d
46 changes: 45 additions & 1 deletion vumi/transports/wechat/wechat.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@

from vumi import log
from vumi.config import (
ConfigText, ConfigServerEndpoint, ConfigDict, ConfigInt)
ConfigText, ConfigServerEndpoint, ConfigDict, ConfigInt, ConfigBool)
from vumi.transports import Transport
from vumi.transports.httprpc.httprpc import HttpRpcHealthResource
from vumi.transports.wechat.errors import WeChatException, WeChatApiException
Expand Down Expand Up @@ -76,6 +76,15 @@ class WeChatConfig(Transport.CONFIG_CLASS):
wechat_mask_lifetime = ConfigInt(
'How long, in seconds, to maintain an address mask for. '
'(default 1 hour)', default=60 * 60 * 1, static=True)
embed_user_profile = ConfigBool(
'Whether or not to embed the WeChat User Profile info in '
'messages received.', required=False, default=False, static=True)
embed_user_profile_lang = ConfigText(
'What language to request User Profile as.', required=False,
default='en', static=True)
embed_user_profile_lifetime = ConfigInt(
'How long to cache User Profiles for.', default=60*60, required=False,
static=True)


class WeChatResource(Resource):
Expand Down Expand Up @@ -173,6 +182,9 @@ class WeChatTransport(Transport):
ACCESS_TOKEN_KEY = 'access_token'
# What key to store the `addr_mask` under in Redis
ADDR_MASK_KEY = 'addr_mask'
# What key to use when constructing the User Profile key
USER_PROFILE_KEY = 'user_profile'

transport_type = 'wechat'

@inlineCallbacks
Expand Down Expand Up @@ -211,6 +223,12 @@ def create_wechat_menu(self, access_token, menu_structure):
'when creating WeChat Menu.' % data)
log.info('WeChat Menu created succesfully.')

def user_profile_key(self, open_id):
return '@'.join([
self.USER_PROFILE_KEY,
open_id,
])

def mask_key(self, user):
return '@'.join([
self.ADDR_MASK_KEY,
Expand Down Expand Up @@ -243,6 +261,12 @@ def handle_raw_inbound_message(self, request, wc_msg):

@inlineCallbacks
def handle_inbound_text_message(self, request, wc_msg):
config = self.get_static_config()
if config.embed_user_profile:
user_profile = yield self.get_user_profile(wc_msg.from_user_name)
else:
user_profile = {}

mask = yield self.get_addr_mask(wc_msg.from_user_name)
msg = yield self.publish_message(
content=wc_msg.content,
Expand All @@ -256,6 +280,7 @@ def handle_inbound_text_message(self, request, wc_msg):
'ToUserName': wc_msg.to_user_name,
'MsgType': 'text',
'MsgId': wc_msg.msg_id,
'UserProfile': user_profile,
}
})
returnValue(msg)
Expand Down Expand Up @@ -377,6 +402,25 @@ def get_access_token(self):
access_token = yield self.request_new_access_token()
returnValue(access_token)

@inlineCallbacks
def get_user_profile(self, open_id):
config = self.get_static_config()
up_key = self.user_profile_key(open_id)
cached_up = yield self.redis.get(open_id)
if cached_up:
returnValue(json.loads(cached_up))

access_token = yield self.get_access_token()
response = yield http_request_full(self.make_url('user/info', {
'access_token': access_token,
'openid': open_id,
'lang': config.embed_user_profile_lang,
}), method='GET')
user_profile = response.delivered_body
yield self.redis.setex(up_key, config.embed_user_profile_lifetime,
user_profile)
returnValue(json.loads(user_profile))

@inlineCallbacks
def request_new_access_token(self):
config = self.get_static_config()
Expand Down

0 comments on commit 8de6ce1

Please sign in to comment.