我正在使用 UCMA 3.0 开发一个应用程序,它将作为服务运行并以即时消息调用的形式定期发送“广播”。我一直在使用“使用 Microsoft Lync Server 2010 进行专业统一通信开发”一书,并且已将所有内容都配置好并且能够建立应用程序端点。
我被困在两个方面。
1)如何获取 Lync 的所有用户的列表?UCMA 能做的一切都以单个用户为中心。例如,它允许我检索给定用户“联系人列表”中存在的所有联系人/组,但不提供任何方法来查询可以添加到其中一个联系人列表中的可用联系人列表。在 MSDN 论坛上,我发现这篇文章让我认为我最好的选择就是直接查询 AD。
2)实际发送广播式 IM 的最佳方式是什么?我的工作前提是尝试类似于我在此代码示例中找到的内容(特别是public void SendIM()
方法)。
因此,从 AD 获取收件人列表(在每个上循环以检查当前存在?),然后使用自动化为集合中的每个收件人进行 IM 呼叫。
那有意义吗?我是否需要检查接收者是否在场,或者我是否只是乐观地拨打 IM 电话,而不管他们当前的状态如何?谁能给我指出一些演示发送 IM 广播的工作代码?您会认为这可能是最常见的用例之一,但 SDK 示例并未涵盖它。提前致谢。
更新: 正如 Lister 所说,没有“广播”方法。我不得不循环访问收件人并拨打电话为每个收件人发送即时消息。我发现我还需要检查收件人的存在状态,因为它也会尝试向离线、忙碌等用户发送消息,从而导致异常。最好只发送到某些存在状态。由于应用程序端点没有用户/组列表,您要么需要使用 AD 和目录服务来确定收件人,要么只需维护您自己的收件人列表。我最终编写了一个工作流,用户可以在其中向自动应用程序端点发送 IM 以选择加入或退出警报广播。该工作流维护一个简单的订阅者数据库表。
/// <summary>
/// Sending of the actual IM to broadcast subscribers. Here we check that the presence of the target recipient
/// is in fact suitable for us to barge in with an alert.
/// </summary>
private void sendIMBroadcast(string sipTarget, byte[] htmlBytes)
{
try {
_appEndpoint.PresenceServices.BeginPresenceQuery(
new List<string>() {sipTarget},
new string[] {"state"},
null,
result =>
{
try
{
// Retrieve the results of the query.
IEnumerable<RemotePresentityNotification> notifications = _appEndpoint.PresenceServices.EndPresenceQuery(result);
// Grab the first notification in the results.
RemotePresentityNotification notification = notifications.FirstOrDefault();
if (notification == null)
{
logger.Warn("Invalid recipient for P1 broadcast: {0}", sipTarget);
return;
}
//ensure presense is one we want to send alert to
//if (notification.AggregatedPresenceState.AvailabilityValue )
long v = notification.AggregatedPresenceState.AvailabilityValue;
bool skip = false;
if (v >= 3000 && v <= 4499)
{
//online
}
else if (v >= 4500 && v <= 5999)
{
//idle online
}
else if (v >= 6000 && v <= 7499)
{
//busy
skip = true;
}
else if (v >= 7500 && v <= 8999)
{
//idle busy
skip = true;
}
else if (v >= 9000 && v <= 11999)
{
//dnd
skip = true;
}
else if (v >= 12000 && v <= 14999)
{
//brb
skip = true;
}
else if (v >= 15000 && v <= 17999)
{
//away
skip = true;
}
else if (v >= 18000)
{
//offline
skip = true;
}
if (skip == true)
{
logger.Debug("Skipping broadcast for user '{0}' due to presense status {1}.", sipTarget, v.ToString());
return;
}
logger.Debug("Sending broadcast for user '{0}' with presense status {1}.", sipTarget, v.ToString());
// Send an IM, create a new Conversation and make call
Conversation conversation = new Conversation(_appEndpoint);
InstantMessagingCall _imCall = new InstantMessagingCall(conversation);
try
{
ToastMessage toast = new ToastMessage("Unassigned P1 Tickets!");
// Establish the IM call.
_imCall.BeginEstablish(sipTarget,
toast,
new CallEstablishOptions(),
result2 =>
{
try
{
// Finish the asynchronous operation.
_imCall.EndEstablish(result2);
_imCall.Flow.BeginSendInstantMessage(
new System.Net.Mime.ContentType("text/html"),
htmlBytes,
ar =>
{
try
{
_imCall.Flow.EndSendInstantMessage(ar);
}
catch (RealTimeException rtex)
{
logger.Error("Failed sending P1 Broadcast Instant Message call.", rtex);
}
},
null
);
}
catch (RealTimeException rtex)
{
// Catch and log exceptions.
logger.Error("Failed establishing IM call", rtex);
}
},
null
);
}
catch (InvalidOperationException ioex)
{
logger.Error("Failed establishing IM call", ioex);
}
}
catch (RealTimeException ex)
{
logger.Error("Presence query failed.", ex);
}
},
null);
}
catch (InvalidOperationException ex)
{
logger.Error("Failed accepting call and querying presence.", ex);
}
}