BotSharp/BotSharp.Channel.Weixin/Models/CustomMessageHandler.cs
2020-09-07 18:17:58 +08:00

376 lines
16 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*----------------------------------------------------------------
Copyright (C) 2018 Senparc
文件名CustomMessageHandler.cs
文件功能描述微信公众号自定义MessageHandler
创建标识Senparc - 20150312
修改标识Senparc - 20171027
修改描述v14.8.3 添加OnUnknownTypeRequest()方法Demo
----------------------------------------------------------------*/
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading;
using Senparc.Weixin.MP.Entities;
using Senparc.Weixin.MP.Entities.Request;
using Senparc.Weixin.MP.MessageHandlers;
using Senparc.Weixin.MP.AdvancedAPIs;
using System.Threading.Tasks;
using Senparc.NeuChar.Entities.Request;
using Senparc.NeuChar.Helpers;
using Senparc.NeuChar.Entities;
using Senparc.Weixin;
using Senparc.Weixin.MP;
using BotSharp.Platform.Models.AiRequest;
using BotSharp.Platform.Abstractions;
using Microsoft.Extensions.Configuration;
using BotSharp.Platform.Dialogflow.Models;
#if NET45
using System.Web;
using System.Configuration;
using System.Web.Configuration;
using Senparc.Weixin.MP.Sample.CommonService.Utilities;
#else
using Microsoft.AspNetCore.Http;
#endif
namespace BotSharp.Channel.Weixin.Models
{
/// <summary>
/// 自定义MessageHandler
/// 把MessageHandler作为基类重写对应请求的处理方法
/// </summary>
public partial class CustomMessageHandler : MessageHandler<CustomMessageContext>
{
/*
* 重要提示v1.5起MessageHandler提供了一个DefaultResponseMessage的抽象方法
* DefaultResponseMessage必须在子类中重写用于返回没有处理过的消息类型也可以用于默认消息如帮助信息等
* 其中所有原OnXX的抽象方法已经都改为虚方法可以不必每个都重写。若不重写默认返回DefaultResponseMessage方法中的结果。
*/
#if !DEBUG || NETSTANDARD1_6 || NETSTANDARD2_0 || NETCOREAPP2_0 || NETCOREAPP2_1
string agentUrl = "http://localhost:12222/App/Weixin/4";
string agentToken = "27C455F496044A87";
string wiweihiKey = "CNadjJuWzyX5bz5Gn+/XoyqiqMa5DjXQ";
#else
//下面的Url和Token可以用其他平台的消息或者到www.weiweihi.com注册微信用户将自动在“微信营销工具”下得到
private string agentUrl = Config.SenparcWeixinSetting.AgentUrl;//这里使用了www.weiweihi.com微信自动托管平台
private string agentToken = Config.SenparcWeixinSetting.AgentToken;//Token
private string wiweihiKey = Config.SenparcWeixinSetting.SenparcWechatAgentKey;//WeiweihiKey专门用于对接www.Weiweihi.com平台获取方式见http://www.weiweihi.com/ApiDocuments/Item/25#51
#endif
#if NET45
private string appId = Config.SenparcWeixinSetting.WeixinAppId;
private string appSecret = Config.SenparcWeixinSetting.WeixinAppSecret;
#else
private string appId = "appId";
private string appSecret = "appSecret";
#endif
/// <summary>
/// 模板消息集合KeycheckCodeValueOpenId
/// </summary>
public static Dictionary<string, string> TemplateMessageCollection = new Dictionary<string, string>();
private IPlatformBuilder<AgentModel> nluPlatform = null;
private readonly IConfiguration config;
public CustomMessageHandler(IPlatformBuilder<AgentModel> nluPlatform, IConfiguration configuration, Stream inputStream, PostModel postModel, int maxRecordCount = 0)
: base(inputStream, postModel, maxRecordCount)
{
this.nluPlatform = nluPlatform;
this.config = configuration;
//这里设置仅用于测试,实际开发可以在外部更全局的地方设置,
//比如MessageHandler<MessageContext>.GlobalGlobalMessageContext.ExpireMinutes = 3。
GlobalMessageContext.ExpireMinutes = 3;
if (!string.IsNullOrEmpty(postModel.AppId))
{
appId = postModel.AppId;//通过第三方开放平台发送过来的请求
}
//在指定条件下,不使用消息去重
base.OmitRepeatedMessageFunc = requestMessage =>
{
var textRequestMessage = requestMessage as RequestMessageText;
if (textRequestMessage != null && textRequestMessage.Content == "容错")
{
return false;
}
return true;
};
}
public override async Task OnExecutingAsync(CancellationToken cancellationToken)
{
var CurrentMessageContext = await GetCurrentMessageContext();
//测试MessageContext.StorageData
if (CurrentMessageContext.StorageData == null)
{
CurrentMessageContext.StorageData = 0;
}
await base.OnExecutingAsync(cancellationToken);
}
public override async Task OnExecutedAsync(CancellationToken cancellationToken)
{
var CurrentMessageContext = await GetCurrentMessageContext();
CurrentMessageContext.StorageData = ((int)CurrentMessageContext.StorageData) + 1;
await base.OnExecutedAsync(cancellationToken);
}
/// <summary>
/// 处理文字请求
/// </summary>
/// <returns></returns>
public override IResponseMessageBase OnTextRequest(RequestMessageText requestMessage)
{
var defaultResponseMessage = base.CreateResponseMessage<ResponseMessageText>();
var requestHandler =
requestMessage.StartHandler()
.Keyword("BotSharp",() =>
{
var result = new StringBuilder();
result.AppendFormat("{0}", "你好欢迎使用BotSharp NLU服务BotSharp通过强大的自然语言理解技术让你更轻松的处理智能回复。");
defaultResponseMessage.Content = result.ToString();
return defaultResponseMessage;
})
.Keyword("再见", () =>
{
var result = new StringBuilder();
result.AppendFormat("{0}", "谢谢使用,再见!");
defaultResponseMessage.Content = result.ToString();
return defaultResponseMessage;
})
.Default(() =>
{
var result = new StringBuilder();
// send text to BotSharp platform emulator
var aIResponse = nluPlatform.TextRequest<AIResponseResult>(new AiRequest
{
Text = requestMessage.Content,
AgentId = config.GetValue<string>("weixinChannel:agentId"),
SessionId = requestMessage.FromUserName
});
result.AppendFormat("{0}", aIResponse.Result.Fulfillment.Speech);
defaultResponseMessage.Content = result.ToString();
return defaultResponseMessage;
});
return requestHandler.GetResponseMessage() as IResponseMessageBase;
}
/// <summary>
/// 处理位置请求
/// </summary>
/// <param name="requestMessage"></param>
/// <returns></returns>
public override IResponseMessageBase OnLocationRequest(RequestMessageLocation requestMessage)
{
var locationService = new LocationService();
var responseMessage = locationService.GetResponseMessage(requestMessage as RequestMessageLocation);
return responseMessage;
}
public override IResponseMessageBase OnShortVideoRequest(RequestMessageShortVideo requestMessage)
{
var responseMessage = this.CreateResponseMessage<ResponseMessageText>();
responseMessage.Content = "您刚才发送的是小视频";
return responseMessage;
}
/// <summary>
/// 处理图片请求
/// </summary>
/// <param name="requestMessage"></param>
/// <returns></returns>
public override IResponseMessageBase OnImageRequest(RequestMessageImage requestMessage)
{
//一隔一返回News或Image格式
if (base.GlobalMessageContext.GetMessageContext(requestMessage).RequestMessages.Count() % 2 == 0)
{
var responseMessage = CreateResponseMessage<ResponseMessageNews>();
responseMessage.Articles.Add(new Article()
{
Title = "您刚才发送了图片信息",
Description = "您发送的图片将会显示在边上",
PicUrl = requestMessage.PicUrl,
Url = "http://sdk.weixin.senparc.com"
});
responseMessage.Articles.Add(new Article()
{
Title = "第二条",
Description = "第二条带连接的内容",
PicUrl = requestMessage.PicUrl,
Url = "http://sdk.weixin.senparc.com"
});
return responseMessage;
}
else
{
var responseMessage = CreateResponseMessage<ResponseMessageImage>();
responseMessage.Image.MediaId = requestMessage.MediaId;
return responseMessage;
}
}
/// <summary>
/// 处理语音请求
/// </summary>
/// <param name="requestMessage"></param>
/// <returns></returns>
public override IResponseMessageBase OnVoiceRequest(RequestMessageVoice requestMessage)
{
var responseMessage = CreateResponseMessage<ResponseMessageMusic>();
//上传缩略图
//var accessToken = Containers.AccessTokenContainer.TryGetAccessToken(appId, appSecret);
var uploadResult = Senparc.Weixin.MP.AdvancedAPIs.MediaApi.UploadTemporaryMedia(appId, UploadMediaFileType.image,
Server.GetMapPath("~/Images/Logo.jpg"));
//设置音乐信息
responseMessage.Music.Title = "天籁之音";
responseMessage.Music.Description = "播放您上传的语音";
responseMessage.Music.MusicUrl = "http://sdk.weixin.senparc.com/Media/GetVoice?mediaId=" + requestMessage.MediaId;
responseMessage.Music.HQMusicUrl = "http://sdk.weixin.senparc.com/Media/GetVoice?mediaId=" + requestMessage.MediaId;
responseMessage.Music.ThumbMediaId = uploadResult.media_id;
//推送一条客服消息
try
{
CustomApi.SendText(appId, WeixinOpenId, "本次上传的音频MediaId" + requestMessage.MediaId);
}
catch
{
}
return responseMessage;
}
/// <summary>
/// 处理视频请求
/// </summary>
/// <param name="requestMessage"></param>
/// <returns></returns>
public override IResponseMessageBase OnVideoRequest(RequestMessageVideo requestMessage)
{
var responseMessage = CreateResponseMessage<ResponseMessageText>();
responseMessage.Content = "您发送了一条视频信息ID" + requestMessage.MediaId;
#region
Task.Factory.StartNew(async () =>
{
//上传素材
var dir = Server.GetMapPath("~/App_Data/TempVideo/");
var file = await MediaApi.GetAsync(appId, requestMessage.MediaId, dir);
var uploadResult = await MediaApi.UploadTemporaryMediaAsync(appId, UploadMediaFileType.video, file, 50000);
await CustomApi.SendVideoAsync(appId, base.WeixinOpenId, uploadResult.media_id, "这是您刚才发送的视频", "这是一条视频消息");
}).ContinueWith(async task =>
{
if (task.Exception != null)
{
WeixinTrace.Log("OnVideoRequest()储存Video过程发生错误", task.Exception.Message);
var msg = string.Format("上传素材出错:{0}\r\n{1}",
task.Exception.Message,
task.Exception.InnerException != null
? task.Exception.InnerException.Message
: null);
await CustomApi.SendTextAsync(appId, base.WeixinOpenId, msg);
}
});
#endregion
return responseMessage;
}
/// <summary>
/// 处理链接消息请求
/// </summary>
/// <param name="requestMessage"></param>
/// <returns></returns>
public override IResponseMessageBase OnLinkRequest(RequestMessageLink requestMessage)
{
var responseMessage = ResponseMessageBase.CreateFromRequestMessage<ResponseMessageText>(requestMessage);
responseMessage.Content = string.Format(@"您发送了一条连接信息:
Title{0}
Description:{1}
Url:{2}", requestMessage.Title, requestMessage.Description, requestMessage.Url);
return responseMessage;
}
public override IResponseMessageBase OnFileRequest(RequestMessageFile requestMessage)
{
var responseMessage = requestMessage.CreateResponseMessage<ResponseMessageText>();
responseMessage.Content = string.Format(@"您发送了一个文件:
文件名:{0}
说明:{1}
大小:{2}
MD5:{3}", requestMessage.Title, requestMessage.Description, requestMessage.FileTotalLen, requestMessage.FileMd5);
return responseMessage;
}
/// <summary>
/// 处理事件请求这个方法一般不用重写这里仅作为示例出现。除非需要在判断具体Event类型以外对Event信息进行统一操作
/// </summary>
/// <param name="requestMessage"></param>
/// <returns></returns>
public override IResponseMessageBase OnEventRequest(IRequestMessageEventBase requestMessage)
{
var eventResponseMessage = base.OnEventRequest(requestMessage);//对于Event下属分类的重写方法CustomerMessageHandler_Events.cs
//TODO: 对Event信息进行统一操作
return eventResponseMessage;
}
public override IResponseMessageBase DefaultResponseMessage(IRequestMessageBase requestMessage)
{
/* 所有没有被处理的消息会默认返回这里的结果,
* 因此,如果想把整个微信请求委托出去(例如需要使用分布式或从其他服务器获取请求),
* 只需要在这里统一发出委托请求,如:
* var responseMessage = MessageAgent.RequestResponseMessage(agentUrl, agentToken, RequestDocument.ToString());
* return responseMessage;
*/
var responseMessage = this.CreateResponseMessage<ResponseMessageText>();
responseMessage.Content = "这条消息来自DefaultResponseMessage。";
return responseMessage;
}
public override IResponseMessageBase OnUnknownTypeRequest(RequestMessageUnknownType requestMessage)
{
/*
* 此方法用于应急处理SDK没有提供的消息类型
* 原始XML可以通过requestMessage.RequestDocument或this.RequestDocument获取到。
* 如果不重写此方法遇到未知的请求类型将会抛出异常v14.8.3 之前的版本就是这么做的)
*/
var msgType = Senparc.NeuChar.Helpers.MsgTypeHelper.GetRequestMsgTypeString(requestMessage.RequestDocument);
var responseMessage = this.CreateResponseMessage<ResponseMessageText>();
responseMessage.Content = "未知消息类型:" + msgType;
WeixinTrace.SendCustomLog("未知请求消息类型", requestMessage.RequestDocument.ToString());//记录到日志中
return responseMessage;
}
}
}