微信开发系列之七 - 使用Redis存储微信聊天记录
In the second blog Wechat development series 2 – development Q&A service using nodejs of this series, we have developed a kind of Q&A service in Wechat which leverages a free Tuning Restful service so that you could chat with this service:
In this blog, I will show the steps how to store all of those conversation logs via Redis, so that you can review the conversations within Wechat app or delete them if necessary.
Implemented feature
Two new sub menus “Review” and “Delete” are developed under menu “Conversation”:
Once Review menu is pressed, the conversation log will be read out from Redis and displayed in Wechat app:
Delete menu will trigger the deletion of the conversation log belonging to current user who has pressed it. Once conversation is deleted, corresponding notification will be sent out if user has pressed the Review menu again.
Implementation detail
(1) Since as before my WeChat server runs on Heroku, which supports Redis as well.
Redis is an open source (BSD licensed), in-memory data structure store, used as a database, cache and message broker. It supports data structures such as strings, hashes, lists, sets, sorted sets with range queries, bitmaps, hyperloglogs and geospatial indexes with radius queries.
In this blog I will use Redis to store conversation logs.
It is very easy in Heroku to enable an application with Redis support, just select your application from drop down list and press Continue:
The default plan “Hobby Dev” is completely for free and enough for this prototype development.
Once done, in you application dashboard you can see the Redis as addon:
and the actual url for this Redis instance is automatically set in application variable which could be used in your program:
You don’t need any additional configuration on Redis, which is now ready for development.
(2) follow the steps in blog Wechat development series 5 – embedded your UI5 application to Wechat app to create menu and two submenu.
It is enough to create menu via postman. You’d better first remove the old menu done in previous blog and recreate a new menu from scratch:
the source code of HTTP post payload for the new menu creation:
{
"button":[
{
"name":"UI5",
"sub_button":[{
"type": "view",
"name": "Jerry List",
"url": "http://wechatjerry.herokuapp.com/ui5"
},{
"type": "click",
"name": "Other UI5 application",
"key": "dataQuery"
}]
},
{
"name":"Conversation",
"sub_button":[{
"type": "click",
"name": "Review",
"key": "review"
},{
"type": "click",
"name": "Delete",
"key": "delete"
}]
}
]
}
(3) Now every time when Tuning service receives a query from end user and is ready to send the answer of this query, add logic to record this conversation detail.
Just add one line for logging in tuning.js:
The conversationLogService is implemented in conversationLogService.js, which simply delegates the logging call to Redis service wrapper module.
Date.prototype.today = function () {
return ((this.getDate() < 10)?"0":"") + this.getDate() +"/"+(((this.getMonth()+1) < 10)?"0":"") + (this.getMonth()+1) +"/"+ this.getFullYear();
}
Date.prototype.timeNow = function () {
return ((this.getHours() < 10)?"0":"") + this.getHours() +":"+ ((this.getMinutes() < 10)?"0":"") + this.getMinutes() +":"+ ((this.getSeconds() < 10)?"0":"") + this.getSeconds();
}
function logConversation(wholeContent, question, answer){
var fromUserId = formattedValue(getXMLNodeValue('FromUserName', wholeContent));
var toUserId = formattedValue(getXMLNodeValue('ToUserName', wholeContent));
var fromUserName = config.userMap[fromUserId] || fromUserId;
var toUserName = config.userMap[toUserId] || toUserId;
var datetime = "Send Time: " + new Date().today() + " " + new Date().timeNow();
redisClient.insert(toUserId, objectToString(fromUserName, toUserName, datetime, question, answer));
};
function objectToString(fromUserName, toUserName, datetime, question, answer){
var record = {
"from": fromUserName,
"to": toUserName,
"sendTime": datetime,
"question": question,
"answer": answer
};
return JSON.stringify(record);
}
function getList(sToUserOpenId){
return redisClient.getList(sToUserOpenId);
}
function deleteLog(sToUserOpenId){
return redisClient.clearList(sToUserOpenId);
}
var oService = {
log: logConversation,
getLog: getList,
deleteLog: deleteLog
}
module.exports = oService;
Redis service wrapper module is implemented in file redisClient.js.
This wrapper module is built on top of open source Redis module for nodejs, whose source code could be found from github: https://github.com/NodeRedis/node_redis
var redis = require("redis"),
client = redis.createClient(process.env.REDIS_URL || "redis://h:p99a8dd0d92871b9ffe7a026e6d70beecd7f2a0e743fa1e2840a58ce048f41c4a@ec2-34-237-158-248.compute-1.amazonaws.com:9479"); // by default localhost will be used!!
client.on("error", function (err) {
console.log("Trouble......... Redis startup failed: " + err);
});
function insertIntoList(sOpenId, oElement){
client.lpush(sOpenId, oElement);
}
function clearList(sOpenId){
return new Promise(function(resolve,reject){
client.del(sOpenId, function(error, count){
if(error){
console.log("error when clear list:" + error);
reject(error);
}
var reply = "list clear successfully";
console.log(reply);
resolve(reply);
});
});
}
function getListContent(sOpenId){
return new Promise(function(resolve,reject){
client.lrange(sOpenId, 0, -1, function(err, reply) {
console.log("content for list: " + sOpenId + " **********: " + reply + "***");
var content = reply;
if( content == ""){
content = "no conversation log found.";
console.log("reject content: " + content);
reject(content);
}
else {
resolve(formatToWechat(content));
}
});
});
}
function formatToWechat(raw){
var formatted = "[" + raw + "]";
var result = "";
var logs = JSON.parse(formatted);
for( var i = 0; i < logs.length; i++){
var record = "record[" + i + "]:" + " [[from]] " + logs[i].from
+ " [[to]] " + logs[i].to + " [[sendTime]] " + logs[i].sendTime + " [[question]] " + logs[i].question
+ " [[answer]] " + logs[i].answer;
if( i === 0){
result = record;
}
else{
result = result + "\n" + "\n" + record;
}
}
return result;
}
var oRedisClient = {
insert: insertIntoList,
clearList: clearList,
getList: getListContent
};
module.exports = oRedisClient;
(4) implement event handling logic when menu “review” and “delete” are pressed.
Corresponding API provided by Redis are called to read log records from Redis or just clear the list where the log records are stored.
要获取更多Jerry的原创文章,请关注公众号"汪子熙":
相关文章
- Twemproxy 代理Redis集群
- 配置 PHP 的 Session 存储到 Redis
- 基于 Redis 的订阅与发布
- centos安装redis
- Kafka,Mq,Redis作为消息队列使用时的差异?
- thinkphp: 用redis存储短信验证码(thinkphp v6.0.12LTS)
- 你一定能看懂的Redis主从复制流程
- Atitit it计算机应用体系图 大数据 爬虫 非结构数据 nosql redis mongodb 分布式存储 es搜索 可视化 多媒体与office 19.1. 14.3 计
- 在 SAP BTP Kyma Runtime 上使用 Redis 读取和存储数据
- scrapy-redis的关键配置
- Redis数据结构的多种用法(转载)
- ssdb底层实现——ssdb底层是leveldb,leveldb根本上是skiplist(例如为存储多个list items,必然有多个item key,而非暴力string cat),用它来做redis的list和set等,势必在数据结构和算法层面上有诸多不适
- 一些开源搜索引擎实现——倒排使用原始文件,列存储Hbase,KV store如levelDB、mongoDB、redis,以及SQL的,如sqlite或者xxSQL
- Redis主从集群切换数据丢失问题
- 大容量类Redis存储--Pika介绍
- C# 中使用 Redis 简单存储
- 【最详细】最新最全Redis面试大全(42道)
- Springboot整合Websocket遇到的坑_websocket session不支持序列化,无法存储至redis_Websocket相关问题总结(Session共享,用户多端登录等)
- K8S 使用NFS存储 动态创建 PVC/PV 并通过 Statefulset 部署 Redis