Google 日历事件中的 IVR 应用






3.20/5 (5投票s)
当Google日历中的事件发生时,通过IVR呼叫用户
关于IVR和Google日历的介绍
许多人都使用日历的经历,它确实方便了我们的工作和生活。但大多数日历都基于文本提醒,这意味着您只能在电脑前收到事件提醒。
所以我认为如果日历能通过电话提醒我。如果我想实现这个想法,我需要一个能提供API的日历,以及一种能通过编程进行呼叫的技术。
幸运的是,这些技术都已经提供了,Google日历和IVR(Interactive Voice Response,交互式语音应答,基于电话呼叫)。
我写了一些文章介绍IVR。您可以在这里查看
Voicent Gateway中使用的IVR
Facebook中使用的IVR
或者,您可以通过Google搜索进行研究,有很多文章介绍它。现在,我们将主要关注Google日历。
Google日历允许客户端应用程序以Google数据API("GData")feed的形式查看和更新日历事件。您的客户端应用程序可以使用Google日历数据API创建新事件,编辑或删除现有事件,以及查询符合特定条件的事件。
日历数据API有许多可能的用途。例如,您可以创建一个用于您团队日历的Web前端,并将Google日历作为后端。或者,您可以根据您组织的事件数据库为Google日历生成一个公共日历进行显示。或者,您可以搜索相关的日历,在这些日历上显示即将发生的事件列表。
您可以阅读这些文章来理解Google日历
这些文章提供了使用.NET客户端库处理Google日历服务的详细介绍和示例。有关设置客户端库的帮助,请参阅入门指南。您将找到添加事件、更新事件、删除事件和查询事件的示例。如果您有兴趣了解更多关于.NET客户端库用于与日历数据API交互的底层协议,请参阅协议选项卡。
阅读完这些之后,您可以继续以下主题。
如何创建日历服务
CalendarService
类代表与日历服务的客户端连接(包括身份验证)。要使用.NET客户端库请求feed,首先实例化一个新的CalendarService
对象并对用户进行身份验证。然后使用Query
方法检索包含用户所有日历条目的CalendarFeed
对象。
您可以通过WebForm或WinForm对用户进行身份验证,WebForm称为
AuthSub代理身份验证,而WinForm称为ClientLogin用户名/密码身份验证。
为了通过AuthSub登录协议对应用程序进行身份验证,您必须获取会话令牌。
首先,为您的应用程序构建一个AuthSubRequest URL,并像下面这样调用.NET客户端库AuthSubUtil.getRequestUrl("http://www.example.com/RetrieveToken", "http://www.google.com/calendar/feeds/", false, true);
getRequestUrl
方法接受几个参数
- "next" URL,即用户登录其帐户并授予访问权限后,Google将重定向到的URL;
- scope,如上一节所述;
- 两个布尔值,一个指示令牌是否将在注册模式下使用,另一个指示令牌之后是否将兑换为会话令牌。
上面的示例显示了一个在未注册模式下(第一个布尔值为false
)的调用,用于稍后将兑换为会话令牌的令牌(第二个布尔值为true
);请根据您的应用程序相应地调整布尔值。
用户在点击Google的AuthSub页面链接并登录后,AuthSub系统会使用您提供的"next" URL将用户重定向回您的应用程序。
当Google重定向回您的应用程序时,令牌会作为查询参数附加到"next" URL。因此,在上面的"next" URL的情况下,用户登录后,Google会重定向到一个类似http://www.example.com/RetrieveToken?token=DQAADKEDE
的URL。因此,令牌可以在ASP页面的Request.QueryString
对象中作为变量访问。
您最初检索到的令牌始终是单次使用的令牌。您可以按照AuthSub文档中的描述,通过AuthSubSessionToken URL将此令牌兑换为会话令牌。您的应用程序可以使用.NET客户端库进行此兑换,如下所示
Session["sessionToken"] = AuthSubUtil.exchangeForSessionToken(Request.QueryString["token"], null);
现在,您可以通过将令牌放在Authorization头中,使用会话令牌对日历服务器的请求进行身份验证。
GAuthSubRequestFactory authFactory = new GAuthSubRequestFactory("cl", "CalendarSampleApp"); authFactory.Token = Session["sessionToken"].ToString(); Service service = new Service("cl", authFactory.ApplicationName); service.RequestFactory = authFactory;
要使用ClientLogin,请调用CalendarService
的setUserCredentials
方法,指定您的客户端代表其发送查询的用户ID和密码。例如
CalendarService myService = new CalendarService("exampleCo-exampleApp-1"); myService.setUserCredentials("jo@gmail.com", "mypassword");
您可以通过向allcalendars feed URL发送一个经过身份验证的GET
请求来获取用户日历的列表
http://www.google.com/calendar/feeds/default/allcalendars/full
您也可以查询以检索经过身份验证的用户有权访问的日历列表
http://www.google.com/calendar/feeds/default/owncalendars/full
在实例化一个新的CalendarService
对象并对用户进行身份验证后,然后使用Query
方法检索包含用户所有日历条目的CalendarFeed
对象。
// Create a CalenderService and authenticate CalendarService myService = new CalendarService("exampleCo-exampleApp-1"); /*The parameter applicationName in the constructor of CalendarService is random, you can enter any name you want.*/ myService.setUserCredentials("jo@gmail.com", "mypassword"); CalendarQuery query = new CalendarQuery(); query.Uri = new Uri("http://www.google.com/calendar/feeds/default/allcalendars/full"); CalendarFeed resultFeed = service.Query(query); Console.WriteLine("Your calendars:\n"); foreach (CalendarEntry entry in resultFeed.Entries) { Console.WriteLine(entry.Title.Text + "\n"); }
CalendarService
是获取Google日历服务的关键,完成之后,您就可以得到您想要的东西了。在下一个主题中,我将按照这个方法获取日历事件的开始时间,并使用IVR进行呼叫。
事件发生时呼叫用户
我的想法是,首先从客户端使用JavaScript回调到服务器端。在服务器端,使用CalendarService查询从Calendar Service检索EventEntry的StartTime。然后将时间字符串返回给客户端,在客户端,使用JavaScript方法setTimeout循环检查返回的时间与客户端时间。当它们相等时,返回到服务器端,构建一个IVR对象来呼叫用户。
这是html代码
<head id="Head1" runat="server"> <title>GetGoogleEvent</title> <script language="javascript" type="text/javascript"> var stopTimmer;//Timeout ID var strReturn;//The value returned from the server function ReceiveDateFromServer(valueReturnFromServer) { document.getElementById("ServerTime").innerHTML = "DateTime of Server:" + valueReturnFromServer; strReturn = valueReturnFromServer; //Start the reminder to remind the user about the Calendar Event. TriggerEvent(); } function GetServerTime(format) { CallBackToServer(format, "");//Send callback to server. } function TriggerEvent() { //Get the current date with US culture. var localDate = Date.parse((new Date()).toString("en-US")); document.getElementById('NowTime').innerHTML = "DateTime of Now:" + (new Date()).toString("en-US"); var serverDate = Date.parse(strReturn); var diff = localDate - serverDate; //Compare the date returned from server with the client date. if (diff >= 0) { /*If the client is on time, then clear the Timeout and start the server event to call user.*/ clearTimeout(stopTimmer); var btnCall = document.getElementById('btnCall'); if (btnCall != null) { btnCall.click();//Call the server event to make a call. } return false; } /*Recurrence,check every 1 second, until the current time equals the time returned from Calendar.*/ stopTimmer = setTimeout("TriggerEvent()", 1000); } </script> </head> <body> <form id="form1" runat="server"> <div> <asp:Button ID="btnStartReminder" runat="server" Text="Start Reminder" OnClientClick="javascript:GetServerTime('');return false;" /> <br /> <br /> <span id="ServerTime"> DateTime of Now<%= DateTime.Now.ToString("yyyy-MM-dd HHHH:mm:ss") %> </span> <br /> <span id="NowTime"></span> <div style="display:none"> <asp:Button ID="btnCall" runat="server" onclick="CallUser" Text="Button" /> </div> </div> </form> </body>
这是代码隐藏
您需要以下using
语句
using System.Globalization; using Google.GData.AccessControl; using Google.GData.Calendar; using Google.GData.Client; using Google.GData.Extensions;
为了进行回调,您的类必须继承自ICallbackEventHandler
接口。
public partial class CalendarEvent : System.Web.UI.Page, ICallbackEventHandler { protected void Page_Load(object sender, EventArgs e) { if (!IsPostBack) { string strRefrence = Page.ClientScript.GetCallbackEventReference( this, "callArgs", "ReceiveDateFromServer", "callContext"); string strCallBack = "function CallBackToServer(callArgs, callContext) {" + strRefrence + "};"; Page.ClientScript.RegisterClientScriptBlock( this.GetType(), "CallBackToServer", strCallBack, true); } private string eventMessage = String.Empty; public string GetCallbackResult() { DateTimeFormatInfo myDTFormatInfo = new CultureInfo("en-US", false).DateTimeFormat; DateTime eventStartTime = DateTime.Now; //Create a CalenderService and authenticate CalendarService calService = new CalendarService("GoogleCalendarAndIVRSampleApp"); calService.setUserCredentials("userid@gmail.com", "password"); string feedUri = "http://www.google.com/calendar/feeds/userid@gmail.com/private/full"; //Get the Calendar Event you wanted. Google.GData.Calendar.EventQuery eventQuery = new Google.GData.Calendar.EventQuery(feedUri); //This is the title of your wanted event. eventQuery.Query = "NewEvent of mine"; EventFeed resultEventFeed = calService.Query(eventQuery); Google.GData.Calendar.EventEntry myEventEntry = (Google.GData.Calendar.EventEntry)resultEventFeed.Entries[0]; //If you want to remind the user when the event starts,you can do like this: eventStartTime = myEventEntry.Times[0].StartTime; //And get the summary of the event. eventMessage = myEventEntry.Summary.Text; //Of cource,you can get the where,etc. return eventStartTime.ToString("F", myDTFormatInfo); } public void RaiseCallbackEvent(string eventArgument) { //You can write some useful code here. } protected void CallUser(object sender, EventArgs e) { //Call user VoicentIVR callUserByIVR = new VoicentIVR("localhost", 1982); callUserByIVR.CallText("User's phone", eventMessage, true); } }
VoicentIVR类包含在ZIP文件中提供的解决方案中,供下载。
顺便说一下,我的环境是VS2008,但我没有使用.NET Framework 3.5的功能,所以我猜测这些代码在VS2005中也能正常工作。
关注点
历史