Skip to content

Commit

Permalink
Updated to latest samples and docs. (microsoftgraph#161)
Browse files Browse the repository at this point in the history
* Updated to latest samples and docs.

* Fix spelling.
  • Loading branch information
ksikorsk authored Jan 28, 2020
1 parent fa830f8 commit 5ec6202
Show file tree
Hide file tree
Showing 30 changed files with 3,870 additions and 1,353 deletions.
16 changes: 2 additions & 14 deletions Samples/Common/Sample.Common.Tests/HeartbeatHandlerTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -85,15 +85,9 @@ public void HeartbeatShouldLogSuccess()
return Task.CompletedTask;
});

Thread.Sleep(TimeSpan.FromSeconds(3));
Thread.Sleep(TimeSpan.FromSeconds(4));
Assert.IsTrue(loggerCount >= 4, $"loggerCount >= 4 failed: loggerCount = {loggerCount}");

handler.Dispose();
loggerCount = 0;

Thread.Sleep(TimeSpan.FromSeconds(1));
Assert.AreEqual(0, loggerCount);

handler.Dispose();
}

Expand Down Expand Up @@ -125,15 +119,9 @@ public void HeartbeatShouldLogFailure()
throw new Exception("Something went wrong!!!");
});

Thread.Sleep(TimeSpan.FromSeconds(3));
Thread.Sleep(TimeSpan.FromSeconds(4));
Assert.IsTrue(errorCount >= 2, $"errorCount >= 2 failed: errorCount = {errorCount}");

handler.Dispose();
errorCount = 0;

Thread.Sleep(TimeSpan.FromSeconds(1));
Assert.AreEqual(0, errorCount);

handler.Dispose();
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -200,6 +200,7 @@ public async Task<RequestValidationResult> ValidateInboundRequestAsync(HttpReque
return new RequestValidationResult { IsValid = false };
}

request.Properties.Add(HttpConstants.HeaderNames.Tenant, tenantClaim.Value);
return new RequestValidationResult { IsValid = true, TenantId = tenantClaim.Value };
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
// <copyright file="AuthenticationWrapper.cs" company="Microsoft Corporation">
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT license.
// </copyright>

namespace Sample.Common.Authentication
{
using System.Net.Http;
using System.Threading.Tasks;
using Microsoft.Graph;
using Microsoft.Graph.Communications.Client.Authentication;
using Microsoft.Graph.Communications.Common;

/// <summary>
/// A wrapper for the <see cref="IRequestAuthenticationProvider"/>
/// that maps to the <see cref="IAuthenticationProvider"/>.
/// </summary>
/// <seealso cref="IRequestAuthenticationProvider" />
/// <seealso cref="IAuthenticationProvider" />
public class AuthenticationWrapper : IRequestAuthenticationProvider, IAuthenticationProvider
{
private readonly IRequestAuthenticationProvider authenticationProvider;
private readonly string tenant;

/// <summary>
/// Initializes a new instance of the <see cref="AuthenticationWrapper"/> class.
/// </summary>
/// <param name="authenticationProvider">The authentication provider.</param>
/// <param name="tenant">The tenant.</param>
public AuthenticationWrapper(IRequestAuthenticationProvider authenticationProvider, string tenant = null)
{
this.authenticationProvider = authenticationProvider.NotNull(nameof(authenticationProvider));
this.tenant = tenant;
}

/// <inheritdoc />
public Task AuthenticateOutboundRequestAsync(HttpRequestMessage request, string tenant)
{
return this.authenticationProvider.AuthenticateOutboundRequestAsync(request, tenant);
}

/// <inheritdoc />
public Task<RequestValidationResult> ValidateInboundRequestAsync(HttpRequestMessage request)
{
return this.authenticationProvider.ValidateInboundRequestAsync(request);
}

/// <inheritdoc />
public Task AuthenticateRequestAsync(HttpRequestMessage request)
{
return this.AuthenticateOutboundRequestAsync(request, this.tenant);
}
}
}
159 changes: 159 additions & 0 deletions Samples/Common/Sample.Common/Transport/GraphClientExtensions.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,159 @@
// <copyright file="GraphClientExtensions.cs" company="Microsoft Corporation">
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT license.
// </copyright>

namespace Sample.Common.Transport
{
using System;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.Graph;
using Microsoft.Graph.Communications.Common;
using Microsoft.Graph.Communications.Common.Transport;

/// <summary>
/// Extensions for <see cref="IGraphClient"/>.
/// </summary>
public static class GraphClientExtensions
{
/// <summary>
/// Sends the asynchronous.
/// </summary>
/// <typeparam name="TRequest">The type of the request.</typeparam>
/// <typeparam name="TResponse">The type of the response.</typeparam>
/// <param name="client">The client.</param>
/// <param name="request">The request.</param>
/// <param name="tenant">The tenant.</param>
/// <param name="scenarioId">The scenario identifier.</param>
/// <param name="cancellationToken">The cancellation token.</param>
/// <returns>
/// The <see cref="IGraphResponse{T}" />.
/// </returns>
public static Task<IGraphResponse<TResponse>> SendAsync<TRequest, TResponse>(
this IGraphClient client,
IGraphRequest<TRequest> request,
string tenant,
Guid scenarioId,
CancellationToken cancellationToken = default(CancellationToken))
where TRequest : class
where TResponse : class
{
if (!string.IsNullOrWhiteSpace(tenant))
{
request.Properties.Add(GraphProperty.Property(HttpConstants.HeaderNames.Tenant, tenant));
}

request.Properties.Add(GraphProperty.RequestProperty(HttpConstants.HeaderNames.ScenarioId, scenarioId));
request.Properties.Add(GraphProperty.RequestProperty(HttpConstants.HeaderNames.ClientRequestId, Guid.NewGuid()));

return client.SendAsync<TRequest, TResponse>(request, cancellationToken);
}

/// <summary>
/// Sends the asynchronous.
/// </summary>
/// <typeparam name="TRequest">The type of the request.</typeparam>
/// <param name="client">The client.</param>
/// <param name="request">The request.</param>
/// <param name="tenant">The tenant.</param>
/// <param name="scenarioId">The scenario identifier.</param>
/// <param name="cancellationToken">The cancellation token.</param>
/// <returns>
/// The <see cref="IGraphResponse{T}" />.
/// </returns>
public static Task<IGraphResponse> SendAsync<TRequest>(
this IGraphClient client,
IGraphRequest<TRequest> request,
string tenant,
Guid scenarioId,
CancellationToken cancellationToken = default(CancellationToken))
where TRequest : class
{
if (!string.IsNullOrWhiteSpace(tenant))
{
request.Properties.Add(GraphProperty.Property(HttpConstants.HeaderNames.Tenant, tenant));
}

request.Properties.Add(GraphProperty.RequestProperty(HttpConstants.HeaderNames.ScenarioId, scenarioId));
request.Properties.Add(GraphProperty.RequestProperty(HttpConstants.HeaderNames.ClientRequestId, Guid.NewGuid()));

return client.SendAsync<TRequest>(request, cancellationToken);
}

/// <summary>
/// Sends the request asynchronously.
/// </summary>
/// <typeparam name="T"><see cref="Type" /> of the content present in the response.</typeparam>
/// <param name="client">The client.</param>
/// <param name="request">The request.</param>
/// <param name="requestType">Type of the request.</param>
/// <param name="tenant">The tenant.</param>
/// <param name="scenarioId">The scenario identifier.</param>
/// <param name="cancellationToken">The cancellation token.</param>
/// <returns>
/// The <see cref="Task" /> returning the generic type.
/// </returns>
public static async Task<T> SendAsync<T>(
this IGraphClient client,
IBaseRequest request,
RequestType requestType,
string tenant,
Guid scenarioId,
CancellationToken cancellationToken = default(CancellationToken))
where T : class
{
var graphRequest = CreateGraphRequest(request, requestType);
var graphResponse = await client
.SendAsync<object, T>(graphRequest, tenant, scenarioId, cancellationToken)
.ConfigureAwait(false);
return graphResponse.Content;
}

/// <summary>
/// Sends the request asynchronously.
/// </summary>
/// <param name="client">The client.</param>
/// <param name="request">The request.</param>
/// <param name="requestType">Type of the request.</param>
/// <param name="tenant">The tenant.</param>
/// <param name="scenarioId">The scenario identifier.</param>
/// <param name="cancellationToken">The cancellation token.</param>
/// <returns>
/// The <see cref="Task" />.
/// </returns>
public static Task SendAsync(
this IGraphClient client,
IBaseRequest request,
RequestType requestType,
string tenant,
Guid scenarioId,
CancellationToken cancellationToken = default(CancellationToken))
{
return client.SendAsync<NoContentMessage>(request, requestType, tenant, scenarioId, cancellationToken);
}

/// <summary>
/// Creates the graph request.
/// This extracts the `RequestBody` object from the `IBaseRequest`.
/// </summary>
/// <param name="request">The request.</param>
/// <param name="requestType">Type of the request.</param>
/// <returns>
/// The <see cref="IGraphRequest{T}" /> from the given <see cref="IBaseRequest" />.
/// </returns>
private static IGraphRequest<object> CreateGraphRequest(
IBaseRequest request,
RequestType requestType)
{
const string requestBodyName = "RequestBody";
var requestObject = request
.NotNull(nameof(request))
.GetPropertyUsingReflection(requestBodyName);

var requestUri = request.GetHttpRequestMessage().RequestUri;

return new GraphRequest<object>(requestUri, requestObject, requestType);
}
}
}
1 change: 0 additions & 1 deletion Samples/V1.0Samples/RemoteMediaSamples/IncidentBot.sln
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ MinimumVisualStudioVersion = 10.0.40219.1
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{DCC9792D-0B15-4167-8A9F-BB5DDDA6E7D6}"
ProjectSection(SolutionItems) = preProject
..\..\configure_cloud.ps1 = ..\..\configure_cloud.ps1
Getting Started with the Remote Media Samples.md = Getting Started with the Remote Media Samples.md
..\Graph.props = ..\Graph.props
..\nuget.config = ..\nuget.config
EndProjectSection
Expand Down
5 changes: 3 additions & 2 deletions changelog.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,14 @@

This changelog covers what's changed in Microsoft Graph Communications SDK and its associated samples.

## Jan 2019
## Jan 2020

- Promoted IncidentBot to v1.0 samples.
- Migrated v1.0 samples to use the 1.2.0.1 SDK and the https://graph.microsoft.com/v1.0 endpoint.
- Migrated beta samples to use the 1.2.0-beta.1 SDK.
- Added `POST ~/call/{id}/keepAlive` API to v1.0 samples.
- Required to persist the call.
- Migrated samples from the `~/app/` endpoint to the `~/communications/` endpoint
- Migrated samples from the `~/app/` endpoint to the `~/communications/` endpoint.

## Dec 2019

Expand Down
30 changes: 17 additions & 13 deletions docs/bot_media/Microsoft.Skype.Bots.Media.AudioMediaBuffer.html
Original file line number Diff line number Diff line change
Expand Up @@ -139,9 +139,7 @@ <h3 id="properties">Properties
</h3>
<a id="Microsoft_Skype_Bots_Media_AudioMediaBuffer_ActiveSpeakers_" data-uid="Microsoft.Skype.Bots.Media.AudioMediaBuffer.ActiveSpeakers*"></a>
<h4 id="Microsoft_Skype_Bots_Media_AudioMediaBuffer_ActiveSpeakers" data-uid="Microsoft.Skype.Bots.Media.AudioMediaBuffer.ActiveSpeakers">ActiveSpeakers</h4>
<div class="markdown level1 summary"><p>Current active speakers in the conference.
The value is the IDs (MediaSourceIds) of the audio source of the active speakers in the conference and does not include bot&apos;s own MediaSourceId.
If there is no active speaker, or there is just silence in the conference, the value is an empty array.</p>
<div class="markdown level1 summary"><p>Current active speakers in the conference.</p>
</div>
<div class="markdown level1 conceptual"></div>
<h5 class="decalaration">Declaration</h5>
Expand All @@ -163,6 +161,10 @@ <h5 class="propertyValue">Property Value</h5>
</tr>
</tbody>
</table>
<h5 id="Microsoft_Skype_Bots_Media_AudioMediaBuffer_ActiveSpeakers_remarks">Remarks</h5>
<div class="markdown level1 remarks"><p>The value is the IDs (MediaSourceIds) of the audio source of the active speakers in the conference and does not include bot&apos;s own MediaSourceId.
If there is no active speaker, or there is just silence in the conference, the value is an empty array.</p>
</div>
<a id="Microsoft_Skype_Bots_Media_AudioMediaBuffer_AudioFormat_" data-uid="Microsoft.Skype.Bots.Media.AudioMediaBuffer.AudioFormat*"></a>
<h4 id="Microsoft_Skype_Bots_Media_AudioMediaBuffer_AudioFormat" data-uid="Microsoft.Skype.Bots.Media.AudioMediaBuffer.AudioFormat">AudioFormat</h4>
<div class="markdown level1 summary"><p>The audio format.</p>
Expand Down Expand Up @@ -213,9 +215,9 @@ <h5 class="propertyValue">Property Value</h5>
</table>
<a id="Microsoft_Skype_Bots_Media_AudioMediaBuffer_IsSilence_" data-uid="Microsoft.Skype.Bots.Media.AudioMediaBuffer.IsSilence*"></a>
<h4 id="Microsoft_Skype_Bots_Media_AudioMediaBuffer_IsSilence" data-uid="Microsoft.Skype.Bots.Media.AudioMediaBuffer.IsSilence">IsSilence</h4>
<div class="markdown level1 summary"><p>Indicates if the received audio media buffer is a silence packet.
This property is populated by the Real-Time Media Platform for Bots on received audio buffers. When
sending buffers via the IAudioSocket.Send API, this property is unused.</p>
<div class="markdown level1 summary"><p>Indicates if the received audio media buffer contains only silence.
This property is set automatically for received audio buffers. When
sending buffers via the Send method, this property is unused.</p>
</div>
<div class="markdown level1 conceptual"></div>
<h5 class="decalaration">Declaration</h5>
Expand All @@ -239,7 +241,7 @@ <h5 class="propertyValue">Property Value</h5>
</table>
<a id="Microsoft_Skype_Bots_Media_AudioMediaBuffer_Length_" data-uid="Microsoft.Skype.Bots.Media.AudioMediaBuffer.Length*"></a>
<h4 id="Microsoft_Skype_Bots_Media_AudioMediaBuffer_Length" data-uid="Microsoft.Skype.Bots.Media.AudioMediaBuffer.Length">Length</h4>
<div class="markdown level1 summary"><p>The length of data in the media buffer.</p>
<div class="markdown level1 summary"><p>The length in bytes of the data in the media buffer.</p>
</div>
<div class="markdown level1 conceptual"></div>
<h5 class="decalaration">Declaration</h5>
Expand All @@ -263,7 +265,7 @@ <h5 class="propertyValue">Property Value</h5>
</table>
<a id="Microsoft_Skype_Bots_Media_AudioMediaBuffer_Timestamp_" data-uid="Microsoft.Skype.Bots.Media.AudioMediaBuffer.Timestamp*"></a>
<h4 id="Microsoft_Skype_Bots_Media_AudioMediaBuffer_Timestamp" data-uid="Microsoft.Skype.Bots.Media.AudioMediaBuffer.Timestamp">Timestamp</h4>
<div class="markdown level1 summary"><p>&quot;Timestamp of when the media content was received by the bot, or if the bot is sending media,
<div class="markdown level1 summary"><p>Timestamp of when the media content was received by the bot, or if the bot is sending media,
the timestamp of when the media was sourced. It is in 100-ns units.
When sourcing media buffers, this property should be set using
the value from the MediaPlatform.GetCurrentTimestamp() API.</p>
Expand All @@ -290,11 +292,7 @@ <h5 class="propertyValue">Property Value</h5>
</table>
<a id="Microsoft_Skype_Bots_Media_AudioMediaBuffer_UnmixedAudioBuffers_" data-uid="Microsoft.Skype.Bots.Media.AudioMediaBuffer.UnmixedAudioBuffers*"></a>
<h4 id="Microsoft_Skype_Bots_Media_AudioMediaBuffer_UnmixedAudioBuffers" data-uid="Microsoft.Skype.Bots.Media.AudioMediaBuffer.UnmixedAudioBuffers">UnmixedAudioBuffers</h4>
<div class="markdown level1 summary"><p>Contains the list of received unmixed audio buffers (up to four at a time).
This is useful for advanced meeting scenarios, such as being able to receive separate audio buffers for individual speakers.
This value is set only on the receive side when the AudioSocketSetting.ReceiveUnmixedMeetingAudio property is set to true.
Creating unmixed audio buffers and sending it on the AudioSocket is not supported.
This property is null when unmixed buffers are not requested</p>
<div class="markdown level1 summary"><p>Contains the list of received unmixed audio buffers (up to four at a time).</p>
</div>
<div class="markdown level1 conceptual"></div>
<h5 class="decalaration">Declaration</h5>
Expand All @@ -316,6 +314,12 @@ <h5 class="propertyValue">Property Value</h5>
</tr>
</tbody>
</table>
<h5 id="Microsoft_Skype_Bots_Media_AudioMediaBuffer_UnmixedAudioBuffers_remarks">Remarks</h5>
<div class="markdown level1 remarks"><p>This is useful for advanced meeting scenarios, such as being able to receive separate audio buffers for individual speakers.
This value is set only on the receive side when the AudioSocketSetting.ReceiveUnmixedMeetingAudio property is set to true.
Creating unmixed audio buffers and sending it on the AudioSocket is not supported.
This property is null when unmixed buffers are not requested.</p>
</div>
<h3 id="methods">Methods
</h3>
<a id="Microsoft_Skype_Bots_Media_AudioMediaBuffer_Dispose_" data-uid="Microsoft.Skype.Bots.Media.AudioMediaBuffer.Dispose*"></a>
Expand Down
Loading

0 comments on commit 5ec6202

Please sign in to comment.