From 14f0398698ad8600a9c746d317dbb47240ecc352 Mon Sep 17 00:00:00 2001 From: Takashi Shinohara Date: Fri, 6 Dec 2024 15:13:37 +0900 Subject: [PATCH] 3.2.0 release --- .github/workflows/build-bot.yml | 24 +- .github/workflows/build-func.yml | 22 -- .github/workflows/build-web.yml | 26 +-- .github/workflows/develop.yml | 6 + .github/workflows/test.yml | 43 ++++ source/server/.vscode/tasks.json | 1 - .../Bots/ActivityBot.cs | 4 +- .../ConfigureServices.cs | 16 +- .../Dialogs/EndMeetingDialog.cs | 212 ++---------------- .../Dialogs/InMeetingDialog.cs | 4 +- .../Dialogs/StartMeetingDialog.cs | 4 +- .../Karamem0.Commistant.Bot/appsettings.json | 2 + .../Cards/EndMeetingAfter.json | 112 +++++++++ .../Cards/EndMeetingBefore.json | 76 +++++++ .../Karamem0.Commistant.Common.csproj | 5 + .../Logging/LoggerExtensions.cs | 2 +- .../Models/AdaptiveCardTemplateArguments.cs | 28 +++ .../Models/AdaptiveCardTemplateNames.cs | 24 ++ .../Models/ConversationPropertyArguments.cs | 4 - .../ConversationPropertyArgumentsValue.cs | 4 - .../Services/AdaptiveCardService.cs | 40 ++++ .../Services/DateTimeService.cs | 4 - .../{QrCodeService.cs => QRCodeService.cs} | 4 +- .../Commands/EndMeetingCommand.cs | 4 +- .../Commands/InMeetingCommand.cs | 4 +- .../Commands/StartMeetingCommand.cs | 4 +- .../ConfigureServices.cs | 15 +- .../Functions/ExecuteCommandFunction.cs | 44 ++-- .../appsettings.json | 6 +- .../Karamem0.Commistant.Functions/host.json | 12 +- .../Commands/EndMeetingCommandTests.cs | 10 +- .../Commands/InMeetingCommandTests.cs | 6 +- .../Commands/StartMeetingCommandTests.cs | 10 +- .../Services/AdaptiveCardServiceTests.cs | 64 ++++++ .../ConfigureServices.cs | 9 +- .../server/Karamem0.Commistant.Web/Program.cs | 2 +- .../Properties/launchSettings.json | 2 +- .../Karamem0.Commistant.Web/appsettings.json | 5 +- 38 files changed, 507 insertions(+), 357 deletions(-) create mode 100644 .github/workflows/test.yml create mode 100644 source/server/Karamem0.Commistant.Common/Cards/EndMeetingAfter.json create mode 100644 source/server/Karamem0.Commistant.Common/Cards/EndMeetingBefore.json create mode 100644 source/server/Karamem0.Commistant.Common/Models/AdaptiveCardTemplateArguments.cs create mode 100644 source/server/Karamem0.Commistant.Common/Models/AdaptiveCardTemplateNames.cs create mode 100644 source/server/Karamem0.Commistant.Common/Services/AdaptiveCardService.cs rename source/server/Karamem0.Commistant.Common/Services/{QrCodeService.cs => QRCodeService.cs} (88%) create mode 100644 source/server/Karamem0.Commistant.Tests/Services/AdaptiveCardServiceTests.cs diff --git a/.github/workflows/build-bot.yml b/.github/workflows/build-bot.yml index 0c9b0d9..7ff3b4b 100644 --- a/.github/workflows/build-bot.yml +++ b/.github/workflows/build-bot.yml @@ -21,22 +21,13 @@ jobs: shell: pwsh run: | $content = Get-Content -Path ${{env.FILE_PATH}} - $content = $content -replace "{{APP_DOMAIN_NAME}}", "${{vars.APP_DOMAIN_NAME}}" + $content = $content -Replace "{{APP_DOMAIN_NAME}}", "${{vars.APP_DOMAIN_NAME}}" Out-File -FilePath ${{env.FILE_PATH}} -InputObject $content -Encoding UTF8 env: FILE_PATH: source/server/Karamem0.Commistant.Bot/wwwroot/index.html - name: Restore source run: dotnet restore working-directory: source/server - - name: Test source - shell: pwsh - run: | - dotnet test ` - Karamem0.Commistant.Tests/Karamem0.Commistant.Tests.csproj ` - --filter TestCategory=Karamem0.Commistant.Bot ` - -p:AltCover=true ` - -- NUnit.TestOutputXml=${{github.workspace}}/source/server/test - working-directory: source/server - name: Build source shell: pwsh run: | @@ -53,16 +44,3 @@ jobs: name: bot path: source/server/build include-hidden-files: true - - name: Upload test results - uses: enricomi/publish-unit-test-result-action/linux@v2 - if: always() - with: - files: source/server/test/*.xml - check_name: Bot test results - - name: Upload coverage reports - uses: codecov/codecov-action@v4 - if: always() - with: - fail_ci_if_error: true - token: ${{secrets.CODECOV_TOKEN}} - slug: karamem0/commistant diff --git a/.github/workflows/build-func.yml b/.github/workflows/build-func.yml index 6eb4f62..01edf70 100644 --- a/.github/workflows/build-func.yml +++ b/.github/workflows/build-func.yml @@ -20,15 +20,6 @@ jobs: - name: Restore source run: dotnet restore working-directory: source/server - - name: Test source - shell: pwsh - run: | - dotnet test ` - Karamem0.Commistant.Tests/Karamem0.Commistant.Tests.csproj ` - --filter TestCategory=Karamem0.Commistant.Functions ` - -p:AltCover=true ` - -- NUnit.TestOutputXml=${{github.workspace}}/source/server/test - working-directory: source/server - name: Build source shell: pwsh run: | @@ -45,16 +36,3 @@ jobs: name: func path: source/server/build include-hidden-files: true - - name: Upload test results - uses: enricomi/publish-unit-test-result-action/linux@v2 - if: always() - with: - files: source/server/test/*.xml - check_name: Func test results - - name: Upload coverage reports - uses: codecov/codecov-action@v4 - if: always() - with: - fail_ci_if_error: true - token: ${{secrets.CODECOV_TOKEN}} - slug: karamem0/commistant diff --git a/.github/workflows/build-web.yml b/.github/workflows/build-web.yml index 1d2a4f8..1e7818f 100644 --- a/.github/workflows/build-web.yml +++ b/.github/workflows/build-web.yml @@ -25,8 +25,8 @@ jobs: shell: pwsh run: | $content = Get-Content -Path ${{env.FILE_PATH}} - $content = $content -replace "{{APP_DOMAIN_NAME}}", "${{vars.APP_DOMAIN_NAME}}" - $content = $content -replace "{{TELEMETRY_CONNECTION_STRING}}", "${{vars.TELEMETRY_CONNECTION_STRING}}" + $content = $content -Replace "{{APP_DOMAIN_NAME}}", "${{vars.APP_DOMAIN_NAME}}" + $content = $content -Replace "{{TELEMETRY_CONNECTION_STRING}}", "${{vars.TELEMETRY_CONNECTION_STRING}}" Out-File -FilePath ${{env.FILE_PATH}} -InputObject $content -Encoding UTF8 env: FILE_PATH: source/client/.env @@ -42,15 +42,6 @@ jobs: - name: Restore server run: dotnet restore working-directory: source/server - - name: Test source - shell: pwsh - run: | - dotnet test ` - Karamem0.Commistant.Tests/Karamem0.Commistant.Tests.csproj ` - --filter TestCategory=Karamem0.Commistant.Web ` - -p:AltCover=true ` - -- NUnit.TestOutputXml=${{github.workspace}}/source/server/test - working-directory: source/server - name: Build source shell: pwsh run: | @@ -67,16 +58,3 @@ jobs: name: web path: source/server/build include-hidden-files: true - - name: Upload test results - uses: enricomi/publish-unit-test-result-action/linux@v2 - if: always() - with: - files: source/server/test/*.xml - check_name: Web test results - - name: Upload coverage reports - uses: codecov/codecov-action@v4 - if: always() - with: - fail_ci_if_error: true - token: ${{secrets.CODECOV_TOKEN}} - slug: karamem0/commistant diff --git a/.github/workflows/develop.yml b/.github/workflows/develop.yml index 3cc0367..2d81011 100644 --- a/.github/workflows/develop.yml +++ b/.github/workflows/develop.yml @@ -4,6 +4,12 @@ on: - develop jobs: + test: + name: Test source + uses: ./.github/workflows/test.yml + secrets: inherit + with: + environment: dev build-bot: name: Build bot uses: ./.github/workflows/build-bot.yml diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml new file mode 100644 index 0000000..00f9179 --- /dev/null +++ b/.github/workflows/test.yml @@ -0,0 +1,43 @@ +on: + workflow_call: + inputs: + environment: + required: true + type: string + +jobs: + run: + name: Run + environment: ${{inputs.environment}} + runs-on: ubuntu-latest + steps: + - name: Checkout repos + uses: actions/checkout@v4 + - name: Setup .NET Core + uses: actions/setup-dotnet@v4 + with: + dotnet-version: 8.x + - name: Restore source + run: dotnet restore + working-directory: source/server + - name: Test source + shell: pwsh + run: | + dotnet test ` + Karamem0.Commistant.Tests/Karamem0.Commistant.Tests.csproj ` + -p:AltCover=true ` + -- NUnit.TestOutputXml=${{github.workspace}}/source/server/test + working-directory: source/server + - name: Upload test results + uses: enricomi/publish-unit-test-result-action/linux@v2 + if: always() + with: + files: source/server/test/*.xml + check_name: Test results + - name: Upload coverage reports + uses: codecov/codecov-action@v4 + if: always() + with: + fail_ci_if_error: true + token: ${{secrets.CODECOV_TOKEN}} + slug: karamem0/commistant diff --git a/source/server/.vscode/tasks.json b/source/server/.vscode/tasks.json index 43e27d8..a0f19fb 100644 --- a/source/server/.vscode/tasks.json +++ b/source/server/.vscode/tasks.json @@ -27,7 +27,6 @@ "/property:GenerateFullPaths=true", "/consoleloggerparameters:NoSummary" ], - "dependsOn": "clean", "problemMatcher": "$msCompile" }, { diff --git a/source/server/Karamem0.Commistant.Bot/Bots/ActivityBot.cs b/source/server/Karamem0.Commistant.Bot/Bots/ActivityBot.cs index fd27088..884b43d 100644 --- a/source/server/Karamem0.Commistant.Bot/Bots/ActivityBot.cs +++ b/source/server/Karamem0.Commistant.Bot/Bots/ActivityBot.cs @@ -28,7 +28,7 @@ namespace Karamem0.Commistant.Bots; public class ActivityBot( ConversationState conversationState, DialogSet dialogSet, - OpenAIService openAIService, + IOpenAIService openAIService, ILogger logger ) : TeamsActivityHandler { @@ -37,7 +37,7 @@ ILogger logger private readonly DialogSet dialogSet = dialogSet; - private readonly OpenAIService openAIService = openAIService; + private readonly IOpenAIService openAIService = openAIService; private readonly ILogger logger = logger; diff --git a/source/server/Karamem0.Commistant.Bot/ConfigureServices.cs b/source/server/Karamem0.Commistant.Bot/ConfigureServices.cs index d57c175..800a284 100644 --- a/source/server/Karamem0.Commistant.Bot/ConfigureServices.cs +++ b/source/server/Karamem0.Commistant.Bot/ConfigureServices.cs @@ -24,6 +24,7 @@ using System; using System.Collections.Generic; using System.Linq; +using System.Text; using System.Threading.Tasks; namespace Karamem0.Commistant; @@ -33,7 +34,7 @@ public static class ConfigureServices public static IServiceCollection AddBots(this IServiceCollection services, IConfiguration configuration) { - var blobContainerUrl = configuration.GetValue("AzureBotStatesStorageUrl") ?? throw new InvalidOperationException(); + var blobContainerUrl = configuration["AzureBotStatesStorageUrl"] ?? throw new InvalidOperationException(); _ = services.AddSingleton(); _ = services.AddSingleton(); _ = services.AddSingleton(new BlobsStorage( @@ -64,18 +65,19 @@ public static IServiceCollection AddDialogs(this IServiceCollection services) public static IServiceCollection AddServices(this IServiceCollection services, IConfiguration configuration) { - var openAIEndpointUrl = configuration.GetValue("AzureOpenAIEndpointUrl") ?? throw new InvalidOperationException(); - var openAIModelName = configuration.GetValue("AzureOpenAIModelName") ?? throw new InvalidOperationException(); + var openAIEndpointUrl = configuration["AzureOpenAIEndpointUrl"] ?? throw new InvalidOperationException(); + var openAIModelName = configuration["AzureOpenAIModelName"] ?? throw new InvalidOperationException(); _ = services.AddScoped(provider => new AzureOpenAIClient( new Uri(openAIEndpointUrl), new DefaultAzureCredential() )); - _ = services.AddScoped(provider => new OpenAIService( - provider.GetRequiredService() ?? throw new InvalidOperationException(), + _ = services.AddScoped(); + _ = services.AddScoped(); + _ = services.AddScoped(provider => new OpenAIService( + provider.GetRequiredService(), openAIModelName )); - _ = services.AddScoped(); - _ = services.AddScoped(); + _ = services.AddScoped(); return services; } diff --git a/source/server/Karamem0.Commistant.Bot/Dialogs/EndMeetingDialog.cs b/source/server/Karamem0.Commistant.Bot/Dialogs/EndMeetingDialog.cs index 7c1c592..e9242f2 100644 --- a/source/server/Karamem0.Commistant.Bot/Dialogs/EndMeetingDialog.cs +++ b/source/server/Karamem0.Commistant.Bot/Dialogs/EndMeetingDialog.cs @@ -6,7 +6,6 @@ // https://github.com/karamem0/commistant/blob/main/LICENSE // -using AdaptiveCards; using AutoMapper; using Karamem0.Commistant.Extensions; using Karamem0.Commistant.Logging; @@ -30,7 +29,8 @@ namespace Karamem0.Commistant.Dialogs; public class EndMeetingDialog( ConversationState conversationState, - QrCodeService qrCodeService, + IAdaptiveCardService adaptiveCardService, + IQRCodeService qrCodeService, IMapper mapper, ILogger logger ) : ComponentDialog @@ -38,7 +38,9 @@ ILogger logger private readonly ConversationState conversationState = conversationState; - private readonly QrCodeService qrCodeService = qrCodeService; + private readonly IAdaptiveCardService adaptiveCardService = adaptiveCardService; + + private readonly IQRCodeService qrCodeService = qrCodeService; private readonly IMapper mapper = mapper; @@ -63,89 +65,17 @@ private async Task BeforeConfirmAsync(WaterfallStepContext ste var property = await accessor.GetAsync(stepContext.Context, () => new(), cancellationToken); var options = (ConversationPropertyArguments?)stepContext.Options; var value = this.mapper.Map(options, property.Clone()); - var card = new AdaptiveCard("1.3") + var arguments = new AdaptiveCardTemplateArguments() { - Body = - [ - new AdaptiveChoiceSetInput() - { - Id = "Schedule", - Label = "スケジュール", - Placeholder = "通知を表示する時間", - Choices = - [ - new() - { - Title = "なし", - Value = "-1" - }, - new() - { - Title = "予定時刻", - Value = "0" - }, - new() - { - Title = "5 分前", - Value = "5" - }, - new() - { - Title = "10 分前", - Value = "10" - }, - new() - { - Title = "15 分前", - Value = "15" - }, - ], - Value = value.EndMeetingSchedule.ToString() - }, - new AdaptiveTextInput() - { - Id = "Message", - IsMultiline = true, - Label = "メッセージ", - Placeholder = "会議後に表示されるメッセージ", - Style = AdaptiveTextInputStyle.Text, - Value = value.EndMeetingMessage - }, - new AdaptiveTextInput() - { - Id = "Url", - Label = "URL", - Placeholder = "会議後に表示されるリンクの URL", - Style = AdaptiveTextInputStyle.Url, - Value = value.EndMeetingUrl - } - ], - Actions = - [ - new AdaptiveSubmitAction() - { - Id = "Submit", - Title = "保存", - Data = new - { - Button = "Submit" - } - }, - new AdaptiveSubmitAction() - { - Id = "Cancel", - Title = "キャンセル", - Data = new - { - Button = "Cancel" - } - } - ] + Schedule = value.EndMeetingSchedule, + Message = value.EndMeetingMessage, + Url = value.EndMeetingUrl, }; + var card = await this.adaptiveCardService.GetCardAsync(AdaptiveCardTemplateNames.EndMeetingBefore, arguments); var activity = MessageFactory.Attachment(new Attachment() { - ContentType = AdaptiveCard.ContentType, - Content = JsonConvert.DeserializeObject(card.ToJson()) + ContentType = "application/vnd.microsoft.card.adaptive", + Content = JsonConvert.DeserializeObject(card) }); this.logger.SettingsUpdating(stepContext.Context.Activity); return await stepContext.PromptAsync( @@ -182,125 +112,23 @@ private async Task AfterConrifmAsync(WaterfallStepContext step } if (stepContext.Context.Activity.ReplyToId is not null) { - var card = new AdaptiveCard("1.3") + var arguments = new AdaptiveCardTemplateArguments() { - Body = - [ - new AdaptiveColumnSet() - { - Columns = - [ - new AdaptiveColumn() - { - Items = - [ - new AdaptiveTextBlock() - { - Text = "スケジュール", - Weight = AdaptiveTextWeight.Bolder - } - ], - Width = "90px" - }, - new AdaptiveColumn() - { - Items = - [ - new AdaptiveTextBlock() - { - Text = property.EndMeetingSchedule switch - { - -1 => "なし", - 0 => "予定時刻", - _ => $"{property.EndMeetingSchedule} 分前" - } - } - ], - Width = "stretch" - } - ], - }, - new AdaptiveColumnSet() - { - Columns = - [ - new AdaptiveColumn() - { - Items = - [ - new AdaptiveTextBlock() - { - Text = "メッセージ", - Weight = AdaptiveTextWeight.Bolder - } - ], - Width = "90px" - }, - new AdaptiveColumn() - { - Items = - [ - new AdaptiveTextBlock() - { - Text = $"{property.EndMeetingMessage}", - Wrap = true - } - ], - Width = "stretch" - } - ] - }, - new AdaptiveColumnSet() - { - Columns = - [ - new AdaptiveColumn() - { - Items = - [ - new AdaptiveTextBlock() - { - Text = "URL", - Weight = AdaptiveTextWeight.Bolder - } - ], - Width = "90px" - }, - new AdaptiveColumn() - { - Items = - [ - new AdaptiveTextBlock() - { - Text = $"{property.EndMeetingUrl}" - } - ], - Width = "stretch" - } - ] - } - ] + Schedule = property.EndMeetingSchedule, + Message = property.EndMeetingMessage }; if (Uri.TryCreate(property.EndMeetingUrl, UriKind.Absolute, out var url)) { var bytes = await this.qrCodeService.CreateAsync(url.ToString(), cancellationToken); var base64 = Convert.ToBase64String(bytes); - card.Body.Add(new AdaptiveImage() - { - AltText = url.ToString(), - Size = AdaptiveImageSize.Large, - Url = new Uri($"data:image/png;base64,{base64}") - }); - card.Actions.Add(new AdaptiveOpenUrlAction() - { - Title = "URL を開く", - Url = url, - }); + arguments.Url = url.ToString(); + arguments.QRCode = $"data:image/png;base64,{base64}"; } + var card = await this.adaptiveCardService.GetCardAsync(AdaptiveCardTemplateNames.EndMeetingBefore, arguments); var activity = MessageFactory.Attachment(new Attachment() { - ContentType = AdaptiveCard.ContentType, - Content = JsonConvert.DeserializeObject(card.ToJson()) + ContentType = "application/vnd.microsoft.card.adaptive", + Content = JsonConvert.DeserializeObject(card) }); activity.Id = stepContext.Context.Activity.ReplyToId; _ = await stepContext.Context.UpdateActivityAsync(activity, cancellationToken); diff --git a/source/server/Karamem0.Commistant.Bot/Dialogs/InMeetingDialog.cs b/source/server/Karamem0.Commistant.Bot/Dialogs/InMeetingDialog.cs index eb167d2..73ddb1d 100644 --- a/source/server/Karamem0.Commistant.Bot/Dialogs/InMeetingDialog.cs +++ b/source/server/Karamem0.Commistant.Bot/Dialogs/InMeetingDialog.cs @@ -30,7 +30,7 @@ namespace Karamem0.Commistant.Dialogs; public class InMeetingDialog( ConversationState conversationState, - QrCodeService qrCodeService, + IQRCodeService qrCodeService, IMapper mapper, ILogger logger ) : ComponentDialog @@ -38,7 +38,7 @@ ILogger logger private readonly ConversationState conversationState = conversationState; - private readonly QrCodeService qrCodeService = qrCodeService; + private readonly IQRCodeService qrCodeService = qrCodeService; private readonly IMapper mapper = mapper; diff --git a/source/server/Karamem0.Commistant.Bot/Dialogs/StartMeetingDialog.cs b/source/server/Karamem0.Commistant.Bot/Dialogs/StartMeetingDialog.cs index dcd1f4c..bd1fdda 100644 --- a/source/server/Karamem0.Commistant.Bot/Dialogs/StartMeetingDialog.cs +++ b/source/server/Karamem0.Commistant.Bot/Dialogs/StartMeetingDialog.cs @@ -30,7 +30,7 @@ namespace Karamem0.Commistant.Dialogs; public class StartMeetingDialog( ConversationState conversationState, - QrCodeService qrCodeService, + IQRCodeService qrCodeService, IMapper mapper, ILogger logger ) : ComponentDialog @@ -38,7 +38,7 @@ ILogger logger private readonly ConversationState conversationState = conversationState; - private readonly QrCodeService qrCodeService = qrCodeService; + private readonly IQRCodeService qrCodeService = qrCodeService; private readonly IMapper mapper = mapper; diff --git a/source/server/Karamem0.Commistant.Bot/appsettings.json b/source/server/Karamem0.Commistant.Bot/appsettings.json index 706d2a4..3ea7b4b 100644 --- a/source/server/Karamem0.Commistant.Bot/appsettings.json +++ b/source/server/Karamem0.Commistant.Bot/appsettings.json @@ -9,6 +9,8 @@ "LogLevel": { "Default": "Information" }, + "EnableAdaptiveSampling": false, + "EnableLiveMetrics": false, "EnableDependencyTrackingTelemetryModule": false, "EnablePerformanceCounterCollectionModule": false } diff --git a/source/server/Karamem0.Commistant.Common/Cards/EndMeetingAfter.json b/source/server/Karamem0.Commistant.Common/Cards/EndMeetingAfter.json new file mode 100644 index 0000000..e65ec28 --- /dev/null +++ b/source/server/Karamem0.Commistant.Common/Cards/EndMeetingAfter.json @@ -0,0 +1,112 @@ +{ + "type": "AdaptiveCard", + "$schema": "http://adaptivecards.io/schemas/adaptive-card.json", + "version": "1.3", + "body": [ + { + "type": "ColumnSet", + "columns": [ + { + "type": "Column", + "items": [ + { + "type": "TextBlock", + "text": "スケジュール", + "weight": "bolder" + } + ], + "width": "90%" + }, + { + "type": "Column", + "items": [ + { + "type": "TextBlock", + "text": "なし", + "$when": "${Schedule < 0}" + }, + { + "type": "TextBlock", + "text": "予定時刻", + "$when": "${Schedule == 0}" + }, + { + "type": "TextBlock", + "text": "${Schedule} 分前", + "$when": "${Schedule > 0}" + } + ], + "width": "stretch" + } + ] + }, + { + "type": "ColumnSet", + "columns": [ + { + "type": "Column", + "items": [ + { + "type": "TextBlock", + "text": "メッセージ", + "weight": "bolder" + } + ], + "width": "90%" + }, + { + "type": "Column", + "items": [ + { + "type": "TextBlock", + "text": "${Message}" + } + ], + "width": "stretch" + } + ] + }, + { + "type": "ColumnSet", + "columns": [ + { + "type": "Column", + "items": [ + { + "type": "TextBlock", + "text": "URL", + "weight": "bolder" + } + ], + "width": "90%" + }, + { + "type": "Column", + "items": [ + { + "type": "TextBlock", + "text": "${Url}" + } + ], + "width": "stretch" + } + ] + }, + { + "type": "Image", + "url": "${QRCode}", + "altText": "${Url}", + "size": "large", + "$when": "${not(empty(QRCode))}" + } + ], + "actions": [ + { + "type": "Action.OpenUrl", + "id": "OpenUrl", + "title": "URL を開く", + "url": "${Url}", + "$when": "${not(empty(Url))}" + } + ] +} diff --git a/source/server/Karamem0.Commistant.Common/Cards/EndMeetingBefore.json b/source/server/Karamem0.Commistant.Common/Cards/EndMeetingBefore.json new file mode 100644 index 0000000..0dd12b8 --- /dev/null +++ b/source/server/Karamem0.Commistant.Common/Cards/EndMeetingBefore.json @@ -0,0 +1,76 @@ +{ + "type": "AdaptiveCard", + "$schema": "http://adaptivecards.io/schemas/adaptive-card.json", + "version": "1.3", + "body": [ + { + "type": "Input.ChoiceSet", + "id": "Schedule", + "label": "スケジュール", + "placeholder": "通知を表示する時間", + "choices": [ + { + "type": "Input.Choice", + "title": "なし", + "value": "-1" + }, + { + "type": "Input.Choice", + "title": "予定時刻", + "value": "0" + }, + { + "type": "Input.Choice", + "title": "5 分前", + "value": "5" + }, + { + "type": "Input.Choice", + "title": "10 分前", + "value": "10" + }, + { + "type": "Input.Choice", + "title": "15 分前", + "value": "15" + } + ], + "value": "${Schedule}" + }, + { + "type": "Input.Text", + "id": "Message", + "label": "メッセージ", + "placeholder": "会議後に表示されるメッセージ", + "isMultiline": true, + "style": "text", + "value": "${Message}" + }, + { + "type": "Input.Text", + "id": "Url", + "label": "URL", + "placeholder": "会議後に表示される URL", + "style": "url", + "value": "${Url}" + } + ], + "actions": [ + { + "type": "Action.Submit", + "id": "Submit", + "title": "保存", + "data": { + "Button": "Submit" + } + }, + { + "type": "Action.Submit", + "id": "Cancel", + "title": "キャンセル", + "data": { + "Button": "Cancel" + } + } + ] +} diff --git a/source/server/Karamem0.Commistant.Common/Karamem0.Commistant.Common.csproj b/source/server/Karamem0.Commistant.Common/Karamem0.Commistant.Common.csproj index 2fd8acd..07f35ef 100644 --- a/source/server/Karamem0.Commistant.Common/Karamem0.Commistant.Common.csproj +++ b/source/server/Karamem0.Commistant.Common/Karamem0.Commistant.Common.csproj @@ -19,6 +19,7 @@ + @@ -28,6 +29,10 @@ + + + + PublicResXFileCodeGenerator diff --git a/source/server/Karamem0.Commistant.Common/Logging/LoggerExtensions.cs b/source/server/Karamem0.Commistant.Common/Logging/LoggerExtensions.cs index 812c9ce..7d3e619 100644 --- a/source/server/Karamem0.Commistant.Common/Logging/LoggerExtensions.cs +++ b/source/server/Karamem0.Commistant.Common/Logging/LoggerExtensions.cs @@ -23,7 +23,7 @@ public static class LoggerExtensions private static readonly Action unhandledError = LoggerMessage.Define( - LogLevel.Error, + LogLevel.Critical, new EventId(1), "[{MemberName}] 予期しない問題が発生しました。" ); diff --git a/source/server/Karamem0.Commistant.Common/Models/AdaptiveCardTemplateArguments.cs b/source/server/Karamem0.Commistant.Common/Models/AdaptiveCardTemplateArguments.cs new file mode 100644 index 0000000..15df71c --- /dev/null +++ b/source/server/Karamem0.Commistant.Common/Models/AdaptiveCardTemplateArguments.cs @@ -0,0 +1,28 @@ +// +// Copyright (c) 2022-2024 karamem0 +// +// This software is released under the MIT License. +// +// https://github.com/karamem0/commistant/blob/main/LICENSE +// + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Karamem0.Commistant.Models; + +public class AdaptiveCardTemplateArguments +{ + + public int Schedule { get; set; } = -1; + + public string? Message { get; set; } + + public string? Url { get; set; } + + public string? QRCode { get; set; } + +} diff --git a/source/server/Karamem0.Commistant.Common/Models/AdaptiveCardTemplateNames.cs b/source/server/Karamem0.Commistant.Common/Models/AdaptiveCardTemplateNames.cs new file mode 100644 index 0000000..0d2d6c7 --- /dev/null +++ b/source/server/Karamem0.Commistant.Common/Models/AdaptiveCardTemplateNames.cs @@ -0,0 +1,24 @@ +// +// Copyright (c) 2022-2024 karamem0 +// +// This software is released under the MIT License. +// +// https://github.com/karamem0/commistant/blob/main/LICENSE +// + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Karamem0.Commistant.Models; + +public static class AdaptiveCardTemplateNames +{ + + public static readonly string EndMeetingBefore = "EndMeetingBefore"; + + public static readonly string EndMeetingAfter = "EndMeetingAfter"; + +} diff --git a/source/server/Karamem0.Commistant.Common/Models/ConversationPropertyArguments.cs b/source/server/Karamem0.Commistant.Common/Models/ConversationPropertyArguments.cs index 44697a5..2987454 100644 --- a/source/server/Karamem0.Commistant.Common/Models/ConversationPropertyArguments.cs +++ b/source/server/Karamem0.Commistant.Common/Models/ConversationPropertyArguments.cs @@ -17,10 +17,6 @@ namespace Karamem0.Commistant.Models; public class ConversationPropertyArguments { - public ConversationPropertyArguments() - { - } - public string? Type { get; set; } public ConversationPropertyArgumentsValue? Value { get; set; } diff --git a/source/server/Karamem0.Commistant.Common/Models/ConversationPropertyArgumentsValue.cs b/source/server/Karamem0.Commistant.Common/Models/ConversationPropertyArgumentsValue.cs index 3447a78..b19774a 100644 --- a/source/server/Karamem0.Commistant.Common/Models/ConversationPropertyArgumentsValue.cs +++ b/source/server/Karamem0.Commistant.Common/Models/ConversationPropertyArgumentsValue.cs @@ -17,10 +17,6 @@ namespace Karamem0.Commistant.Models; public class ConversationPropertyArgumentsValue { - public ConversationPropertyArgumentsValue() - { - } - public bool Enabled { get; set; } public int Schedule { get; set; } = -1; diff --git a/source/server/Karamem0.Commistant.Common/Services/AdaptiveCardService.cs b/source/server/Karamem0.Commistant.Common/Services/AdaptiveCardService.cs new file mode 100644 index 0000000..cdd9d64 --- /dev/null +++ b/source/server/Karamem0.Commistant.Common/Services/AdaptiveCardService.cs @@ -0,0 +1,40 @@ +// +// Copyright (c) 2022-2024 karamem0 +// +// This software is released under the MIT License. +// +// https://github.com/karamem0/commistant/blob/main/LICENSE +// + +using AdaptiveCards.Templating; +using Karamem0.Commistant.Models; +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Karamem0.Commistant.Services; + +public interface IAdaptiveCardService +{ + + Task GetCardAsync(string template, AdaptiveCardTemplateArguments arguments); + +} + +public class AdaptiveCardService : IAdaptiveCardService +{ + + private static readonly string templatePath = "Karamem0.Commistant.Cards"; + + public async Task GetCardAsync(string template, AdaptiveCardTemplateArguments arguments) + { + var path = $"{templatePath}.{template}.json"; + using var stream = this.GetType().Assembly.GetManifestResourceStream(path) ?? throw new InvalidOperationException(); + using var reader = new StreamReader(stream); + return new AdaptiveCardTemplate(await reader.ReadToEndAsync()).Expand(arguments); + } + +} diff --git a/source/server/Karamem0.Commistant.Common/Services/DateTimeService.cs b/source/server/Karamem0.Commistant.Common/Services/DateTimeService.cs index a436973..af06ab1 100644 --- a/source/server/Karamem0.Commistant.Common/Services/DateTimeService.cs +++ b/source/server/Karamem0.Commistant.Common/Services/DateTimeService.cs @@ -24,10 +24,6 @@ public interface IDateTimeService public class DateTimeService : IDateTimeService { - public DateTimeService() - { - } - public DateTime GetCurrentDateTime() { return DateTime.UtcNow; diff --git a/source/server/Karamem0.Commistant.Common/Services/QrCodeService.cs b/source/server/Karamem0.Commistant.Common/Services/QRCodeService.cs similarity index 88% rename from source/server/Karamem0.Commistant.Common/Services/QrCodeService.cs rename to source/server/Karamem0.Commistant.Common/Services/QRCodeService.cs index 1975b69..3470e5b 100644 --- a/source/server/Karamem0.Commistant.Common/Services/QrCodeService.cs +++ b/source/server/Karamem0.Commistant.Common/Services/QRCodeService.cs @@ -16,14 +16,14 @@ namespace Karamem0.Commistant.Services; -public interface IQrCodeService +public interface IQRCodeService { Task CreateAsync(string text, CancellationToken cancellationToken = default); } -public class QrCodeService(QRCodeGenerator qrCodeGenerator) : IQrCodeService +public class QRCodeService(QRCodeGenerator qrCodeGenerator) : IQRCodeService { private readonly QRCodeGenerator qrCodeGenerator = qrCodeGenerator; diff --git a/source/server/Karamem0.Commistant.Functions/Commands/EndMeetingCommand.cs b/source/server/Karamem0.Commistant.Functions/Commands/EndMeetingCommand.cs index 5d3f953..126ecdf 100644 --- a/source/server/Karamem0.Commistant.Functions/Commands/EndMeetingCommand.cs +++ b/source/server/Karamem0.Commistant.Functions/Commands/EndMeetingCommand.cs @@ -27,7 +27,7 @@ namespace Karamem0.Commistant.Commands; public class EndMeetingCommand( IDateTimeService dateTimeService, IConnectorClientService connectorClientService, - IQrCodeService qrCodeService, + IQRCodeService qrCodeService, ILogger logger ) : Command() { @@ -36,7 +36,7 @@ ILogger logger private readonly IConnectorClientService connectorClientService = connectorClientService; - private readonly IQrCodeService qrCodeService = qrCodeService; + private readonly IQRCodeService qrCodeService = qrCodeService; private readonly ILogger logger = logger; diff --git a/source/server/Karamem0.Commistant.Functions/Commands/InMeetingCommand.cs b/source/server/Karamem0.Commistant.Functions/Commands/InMeetingCommand.cs index 7fb1d6a..1f93402 100644 --- a/source/server/Karamem0.Commistant.Functions/Commands/InMeetingCommand.cs +++ b/source/server/Karamem0.Commistant.Functions/Commands/InMeetingCommand.cs @@ -27,7 +27,7 @@ namespace Karamem0.Commistant.Commands; public class InMeetingCommand( IDateTimeService dateTimeService, IConnectorClientService connectorClientService, - IQrCodeService qrCodeService, + IQRCodeService qrCodeService, ILogger logger ) : Command() { @@ -36,7 +36,7 @@ ILogger logger private readonly IConnectorClientService connectorClientService = connectorClientService; - private readonly IQrCodeService qrCodeService = qrCodeService; + private readonly IQRCodeService qrCodeService = qrCodeService; private readonly ILogger logger = logger; diff --git a/source/server/Karamem0.Commistant.Functions/Commands/StartMeetingCommand.cs b/source/server/Karamem0.Commistant.Functions/Commands/StartMeetingCommand.cs index db2ddd7..5c18b67 100644 --- a/source/server/Karamem0.Commistant.Functions/Commands/StartMeetingCommand.cs +++ b/source/server/Karamem0.Commistant.Functions/Commands/StartMeetingCommand.cs @@ -27,7 +27,7 @@ namespace Karamem0.Commistant.Commands; public class StartMeetingCommand( IDateTimeService dateTimeService, IConnectorClientService connectorClientService, - IQrCodeService qrCodeService, + IQRCodeService qrCodeService, ILogger logger ) : Command() { @@ -36,7 +36,7 @@ ILogger logger private readonly IConnectorClientService connectorClientService = connectorClientService; - private readonly IQrCodeService qrCodeService = qrCodeService; + private readonly IQRCodeService qrCodeService = qrCodeService; private readonly ILogger logger = logger; diff --git a/source/server/Karamem0.Commistant.Functions/ConfigureServices.cs b/source/server/Karamem0.Commistant.Functions/ConfigureServices.cs index 4a73dbe..f73677f 100644 --- a/source/server/Karamem0.Commistant.Functions/ConfigureServices.cs +++ b/source/server/Karamem0.Commistant.Functions/ConfigureServices.cs @@ -29,25 +29,28 @@ public static class ConfigureServices public static IServiceCollection AddBlobContainerClient(this IServiceCollection services, IConfiguration configuration) { - var blobContainerUrl = configuration.GetValue("AzureBotStatesStorageUrl") ?? throw new InvalidOperationException(); + var blobContainerUrl = configuration["AzureBotStatesStorageUrl"] ?? throw new InvalidOperationException(); _ = services.AddSingleton(provider => new BlobContainerClient(new Uri(blobContainerUrl), new DefaultAzureCredential())); return services; } public static IServiceCollection AddServiceClientCredentials(this IServiceCollection services, IConfiguration configuration) { + var microsoftAppId = configuration["MicrosoftAppId"] ?? throw new InvalidOperationException(); + var microsoftAppPassword = configuration["MicrosoftAppPassword"] ?? throw new InvalidOperationException(); _ = services.AddSingleton(new MicrosoftAppCredentials( - configuration.GetValue("MicrosoftAppId"), - configuration.GetValue("MicrosoftAppPassword"))); + microsoftAppId, + microsoftAppPassword + )); return services; } public static IServiceCollection AddServices(this IServiceCollection services) { - _ = services.AddScoped(); - _ = services.AddScoped(); _ = services.AddScoped(); - _ = services.AddScoped(); + _ = services.AddScoped(); + _ = services.AddScoped(); + _ = services.AddScoped(); return services; } diff --git a/source/server/Karamem0.Commistant.Functions/Functions/ExecuteCommandFunction.cs b/source/server/Karamem0.Commistant.Functions/Functions/ExecuteCommandFunction.cs index 70f8e2a..cfd7b85 100644 --- a/source/server/Karamem0.Commistant.Functions/Functions/ExecuteCommandFunction.cs +++ b/source/server/Karamem0.Commistant.Functions/Functions/ExecuteCommandFunction.cs @@ -44,38 +44,36 @@ public async Task Run([TimerTrigger("0 */1 * * * *")] object timerInfo) try { this.logger.TimerStarted(); - await foreach (var blobPage in this.botStateClient.GetBlobsAsync().AsPages()) + await foreach (var blobItem in this.botStateClient.GetBlobsAsync()) { - foreach (var blobItem in blobPage.Values) + var blobClient = this.botStateClient.GetBlobClient(blobItem.Name); + var blobContent = await blobClient.GetObjectAsync>(); + if (blobContent.Data is null) { - var blobClient = this.botStateClient.GetBlobClient(blobItem.Name); - var blobContent = await blobClient.GetObjectAsync>(); - if (blobContent.Data is null) - { - continue; - } - var property = blobContent.Data.GetValueOrDefault(nameof(ConversationProperty)); - if (property is null) - { - continue; - } - var reference = blobContent.Data.GetValueOrDefault(nameof(ConversationReference)); - if (reference is null) - { - continue; - } - var cd = await this.commandSet.CreateContextAsync(property, reference); - await cd.ExecuteCommandAsync(nameof(StartMeetingCommand)); - await cd.ExecuteCommandAsync(nameof(EndMeetingCommand)); - await cd.ExecuteCommandAsync(nameof(InMeetingCommand)); - await blobClient.SetObjectAsync(blobContent); + continue; } + var property = blobContent.Data.GetValueOrDefault(nameof(ConversationProperty)); + if (property is null) + { + continue; + } + var reference = blobContent.Data.GetValueOrDefault(nameof(ConversationReference)); + if (reference is null) + { + continue; + } + var cd = await this.commandSet.CreateContextAsync(property, reference); + await cd.ExecuteCommandAsync(nameof(StartMeetingCommand)); + await cd.ExecuteCommandAsync(nameof(EndMeetingCommand)); + await cd.ExecuteCommandAsync(nameof(InMeetingCommand)); + await blobClient.SetObjectAsync(blobContent); } this.logger.TimerEnded(); } catch (Exception ex) { this.logger.UnhandledError(ex); + throw; } } diff --git a/source/server/Karamem0.Commistant.Functions/appsettings.json b/source/server/Karamem0.Commistant.Functions/appsettings.json index 3d7da11..e2fa34b 100644 --- a/source/server/Karamem0.Commistant.Functions/appsettings.json +++ b/source/server/Karamem0.Commistant.Functions/appsettings.json @@ -8,7 +8,11 @@ "ApplicationInsights": { "LogLevel": { "Default": "Information" - } + }, + "EnableAdaptiveSampling": false, + "EnableLiveMetrics": false, + "EnableDependencyTrackingTelemetryModule": false, + "EnablePerformanceCounterCollectionModule": false } }, "AzureBotStatesStorageUrl": "", diff --git a/source/server/Karamem0.Commistant.Functions/host.json b/source/server/Karamem0.Commistant.Functions/host.json index db48255..d2059a4 100644 --- a/source/server/Karamem0.Commistant.Functions/host.json +++ b/source/server/Karamem0.Commistant.Functions/host.json @@ -1,13 +1,3 @@ { - "version": "2.0", - "logging": { - "logLevel": { - "default": "Information" - }, - "applicationInsights": { - "samplingSettings": { - "isEnabled": false - } - } - } + "version": "2.0" } diff --git a/source/server/Karamem0.Commistant.Tests/Functions/Commands/EndMeetingCommandTests.cs b/source/server/Karamem0.Commistant.Tests/Functions/Commands/EndMeetingCommandTests.cs index a1975e4..fec56ec 100644 --- a/source/server/Karamem0.Commistant.Tests/Functions/Commands/EndMeetingCommandTests.cs +++ b/source/server/Karamem0.Commistant.Tests/Functions/Commands/EndMeetingCommandTests.cs @@ -54,7 +54,7 @@ public async Task EndMeetingCommand_ExecuteAsync_Succeeded_OnSchedule() var connectorClientService = Substitute.For(); _ = connectorClientService.SendActivityAsync(new Uri("https://www.example.com/"), Arg.Any()) .Returns(new ResourceResponse()); - var qrCodeService = Substitute.For(); + var qrCodeService = Substitute.For(); _ = qrCodeService.CreateAsync("https://www.example.com/") .Returns([]); var logger = Substitute.For>(); @@ -109,7 +109,7 @@ public async Task EndMeetingCommand_ExecuteAsync_Succeeded_AfterSchedule() var connectorClientService = Substitute.For(); _ = connectorClientService.SendActivityAsync(new Uri("https://www.example.com/"), Arg.Any()) .Returns(new ResourceResponse()); - var qrCodeService = Substitute.For(); + var qrCodeService = Substitute.For(); _ = qrCodeService.CreateAsync("https://www.example.com/") .Returns([]); var logger = Substitute.For>(); @@ -166,7 +166,7 @@ public async Task EndMeetingCommand_ExecuteAsync_Skipped_BeforeSchedule() _ = connectorClientService .SendActivityAsync(new Uri("https://www.example.com/"), Arg.Any()) .Returns(new ResourceResponse()); - var qrCodeService = Substitute.For(); + var qrCodeService = Substitute.For(); _ = qrCodeService.CreateAsync("https://www.example.com/") .Returns([]); var logger = Substitute.For>(); @@ -223,7 +223,7 @@ public async Task EndMeetingCommand_ExecuteAsync_Skipped_NotInMeeting() _ = connectorClientService .SendActivityAsync(new Uri("https://www.example.com/"), Arg.Any()) .Returns(new ResourceResponse()); - var qrCodeService = Substitute.For(); + var qrCodeService = Substitute.For(); _ = qrCodeService .CreateAsync("https://www.example.com/") .Returns([]); @@ -281,7 +281,7 @@ public async Task EndMeetingCommand_ExecuteAsync_Skipped_AfterSended() _ = connectorClientService .SendActivityAsync(new Uri("https://www.example.com/"), Arg.Any()) .Returns(new ResourceResponse()); - var qrCodeService = Substitute.For(); + var qrCodeService = Substitute.For(); _ = qrCodeService .CreateAsync("https://www.example.com/") .Returns([]); diff --git a/source/server/Karamem0.Commistant.Tests/Functions/Commands/InMeetingCommandTests.cs b/source/server/Karamem0.Commistant.Tests/Functions/Commands/InMeetingCommandTests.cs index 6e67a62..3fa3c75 100644 --- a/source/server/Karamem0.Commistant.Tests/Functions/Commands/InMeetingCommandTests.cs +++ b/source/server/Karamem0.Commistant.Tests/Functions/Commands/InMeetingCommandTests.cs @@ -53,7 +53,7 @@ public async Task InMeetingCommand_ExecuteAsync_Succeeded_OnSchedule() var connectorClientService = Substitute.For(); _ = connectorClientService.SendActivityAsync(new Uri("https://www.example.com/"), Arg.Any()) .Returns(new ResourceResponse()); - var qrCodeService = Substitute.For(); + var qrCodeService = Substitute.For(); _ = qrCodeService.CreateAsync("https://www.example.com/") .Returns([]); var logger = Substitute.For>(); @@ -106,7 +106,7 @@ public async Task InMeetingCommand_ExecuteAsync_Skipped_OffSchedule() var connectorClientService = Substitute.For(); _ = connectorClientService.SendActivityAsync(new Uri("https://www.example.com/"), Arg.Any()) .Returns(new ResourceResponse()); - var qrCodeService = Substitute.For(); + var qrCodeService = Substitute.For(); _ = qrCodeService.CreateAsync("https://www.example.com/") .Returns([]); var logger = Substitute.For>(); @@ -159,7 +159,7 @@ public async Task InMeetingCommand_ExecuteAsync_Skipped_NotInMeeting() var connectorClientService = Substitute.For(); _ = connectorClientService.SendActivityAsync(new Uri("https://www.example.com/"), Arg.Any()) .Returns(new ResourceResponse()); - var qrCodeService = Substitute.For(); + var qrCodeService = Substitute.For(); _ = qrCodeService.CreateAsync("https://www.example.com/") .Returns([]); var logger = Substitute.For>(); diff --git a/source/server/Karamem0.Commistant.Tests/Functions/Commands/StartMeetingCommandTests.cs b/source/server/Karamem0.Commistant.Tests/Functions/Commands/StartMeetingCommandTests.cs index f74cbdd..61f375e 100644 --- a/source/server/Karamem0.Commistant.Tests/Functions/Commands/StartMeetingCommandTests.cs +++ b/source/server/Karamem0.Commistant.Tests/Functions/Commands/StartMeetingCommandTests.cs @@ -54,7 +54,7 @@ public async Task StartMeetingCommand_ExecuteAsync_Succeeded_OnSchedule() var connectorClientService = Substitute.For(); _ = connectorClientService.SendActivityAsync(new Uri("https://www.example.com/"), Arg.Any()) .Returns(new ResourceResponse()); - var qrCodeService = Substitute.For(); + var qrCodeService = Substitute.For(); _ = qrCodeService.CreateAsync("https://www.example.com/") .Returns([]); var logger = Substitute.For>(); @@ -109,7 +109,7 @@ public async Task StartMeetingCommand_ExecuteAsync_Succeeded_AfterSchedule() var connectorClientService = Substitute.For(); _ = connectorClientService.SendActivityAsync(new Uri("https://www.example.com/"), Arg.Any()) .Returns(new ResourceResponse()); - var qrCodeService = Substitute.For(); + var qrCodeService = Substitute.For(); _ = qrCodeService.CreateAsync("https://www.example.com/") .Returns([]); var logger = Substitute.For>(); @@ -164,7 +164,7 @@ public async Task StartMeetingCommand_ExecuteAsync_Skipped_BeforeSchedule() var connectorClientService = Substitute.For(); _ = connectorClientService.SendActivityAsync(new Uri("https://www.example.com/"), Arg.Any()) .Returns(new ResourceResponse()); - var qrCodeService = Substitute.For(); + var qrCodeService = Substitute.For(); _ = qrCodeService.CreateAsync("https://www.example.com/") .Returns([]); var logger = Substitute.For>(); @@ -219,7 +219,7 @@ public async Task StartMeetingCommand_ExecuteAsync_Skipped_NotInMeeting() var connectorClientService = Substitute.For(); _ = connectorClientService.SendActivityAsync(new Uri("https://www.example.com/"), Arg.Any()) .Returns(new ResourceResponse()); - var qrCodeService = Substitute.For(); + var qrCodeService = Substitute.For(); _ = qrCodeService.CreateAsync("https://www.example.com/") .Returns([]); var logger = Substitute.For>(); @@ -274,7 +274,7 @@ public async Task StartMeetingCommand_ExecuteAsync_Skipped_AfterSended() var connectorClientService = Substitute.For(); _ = connectorClientService.SendActivityAsync(new Uri("https://www.example.com/"), Arg.Any()) .Returns(new ResourceResponse()); - var qrCodeService = Substitute.For(); + var qrCodeService = Substitute.For(); _ = qrCodeService.CreateAsync("https://www.example.com/") .Returns([]); var logger = Substitute.For>(); diff --git a/source/server/Karamem0.Commistant.Tests/Services/AdaptiveCardServiceTests.cs b/source/server/Karamem0.Commistant.Tests/Services/AdaptiveCardServiceTests.cs new file mode 100644 index 0000000..e9c0fe8 --- /dev/null +++ b/source/server/Karamem0.Commistant.Tests/Services/AdaptiveCardServiceTests.cs @@ -0,0 +1,64 @@ +// +// Copyright (c) 2022-2024 karamem0 +// +// This software is released under the MIT License. +// +// https://github.com/karamem0/commistant/blob/main/LICENSE +// + +using Karamem0.Commistant.Models; +using NUnit.Framework; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Karamem0.Commistant.Services.Tests; + +[Category("Karamem0.Commistant.Services")] +public class AdaptiveCardServiceTests +{ + + [Test()] + public async Task GetCardAsync_EndMeetingBefore_ReturnsCard() + { + var service = new AdaptiveCardService(); + var arguments = new AdaptiveCardTemplateArguments() + { + Schedule = 15, + Message = "Hello, World!", + Url = "https://www.example.com" + }; + var actual = await service.GetCardAsync(AdaptiveCardTemplateNames.EndMeetingBefore, arguments); + Assert.That(actual, Is.Not.Null); + } + + [Test()] + public async Task GetCardAsync_EndMeetingAfter_ReturnsCard() + { + var service = new AdaptiveCardService(); + var arguments = new AdaptiveCardTemplateArguments() + { + Schedule = 15, + Message = "Hello, World!", + Url = "https://www.example.com" + }; + var actual = await service.GetCardAsync(AdaptiveCardTemplateNames.EndMeetingAfter, arguments); + Assert.That(actual, Is.Not.Null); + } + + [Test()] + public void GetCardAsync_InvalidName_ThrowsException() + { + var service = new AdaptiveCardService(); + var arguments = new AdaptiveCardTemplateArguments() + { + Schedule = 15, + Message = "Hello, World!", + Url = "https://www.example.com" + }; + _ = Assert.ThrowsAsync(() => service.GetCardAsync("", arguments)); + } + +} diff --git a/source/server/Karamem0.Commistant.Web/ConfigureServices.cs b/source/server/Karamem0.Commistant.Web/ConfigureServices.cs index f7b8f44..eb38ca0 100644 --- a/source/server/Karamem0.Commistant.Web/ConfigureServices.cs +++ b/source/server/Karamem0.Commistant.Web/ConfigureServices.cs @@ -25,16 +25,19 @@ public static class ConfigureServices public static IServiceCollection AddBlobContainerClient(this IServiceCollection services, IConfiguration configuration) { - var blobContainerUrl = configuration.GetValue("AzureBotStatesStorageUrl") ?? throw new InvalidOperationException(); + var blobContainerUrl = configuration["AzureBotStatesStorageUrl"] ?? throw new InvalidOperationException(); _ = services.AddSingleton(provider => new BlobContainerClient(new Uri(blobContainerUrl), new DefaultAzureCredential())); return services; } public static IServiceCollection AddServiceClientCredentials(this IServiceCollection services, IConfiguration configuration) { + var microsoftAppId = configuration["MicrosoftAppId"] ?? throw new InvalidOperationException(); + var microsoftAppPassword = configuration["MicrosoftAppPassword"] ?? throw new InvalidOperationException(); _ = services.AddSingleton(new MicrosoftAppCredentials( - configuration.GetValue("MicrosoftAppId"), - configuration.GetValue("MicrosoftAppPassword"))); + microsoftAppId, + microsoftAppPassword + )); return services; } diff --git a/source/server/Karamem0.Commistant.Web/Program.cs b/source/server/Karamem0.Commistant.Web/Program.cs index cfd5808..bb43721 100644 --- a/source/server/Karamem0.Commistant.Web/Program.cs +++ b/source/server/Karamem0.Commistant.Web/Program.cs @@ -26,7 +26,7 @@ _ = services.AddAutoMapper(config => config.AddProfile()); _ = services.AddBlobContainerClient(configuration); _ = services.AddServiceClientCredentials(configuration); -_ = services.AddMicrosoftIdentityWebApiAuthentication(configuration, "AzureAD"); +_ = services.AddMicrosoftIdentityWebApiAuthentication(configuration, "MicrosoftEntra"); _ = services.AddControllers(); _ = services.AddHttpClient(); _ = services.AddCors(options => diff --git a/source/server/Karamem0.Commistant.Web/Properties/launchSettings.json b/source/server/Karamem0.Commistant.Web/Properties/launchSettings.json index 5b77ca9..8146d41 100644 --- a/source/server/Karamem0.Commistant.Web/Properties/launchSettings.json +++ b/source/server/Karamem0.Commistant.Web/Properties/launchSettings.json @@ -3,7 +3,7 @@ "Karamem0.Commistant.Web": { "commandName": "Project", "dotnetRunMessages": true, - "launchBrowser": false, + "launchBrowser": true, "applicationUrl": "https://localhost:5001;http://localhost:5000", "environmentVariables": { "ASPNETCORE_ENVIRONMENT": "Development" diff --git a/source/server/Karamem0.Commistant.Web/appsettings.json b/source/server/Karamem0.Commistant.Web/appsettings.json index 1707856..a89d275 100644 --- a/source/server/Karamem0.Commistant.Web/appsettings.json +++ b/source/server/Karamem0.Commistant.Web/appsettings.json @@ -1,5 +1,4 @@ { - "AllowedHosts": "*", "Logging": { "LogLevel": { "Default": "Information", @@ -10,11 +9,13 @@ "LogLevel": { "Default": "Information" }, + "EnableAdaptiveSampling": false, + "EnableLiveMetrics": false, "EnableDependencyTrackingTelemetryModule": false, "EnablePerformanceCounterCollectionModule": false } }, - "AzureAD": { + "MicrosoftEntra": { "Audience": "", "ClientId": "", "ClientSecret": "",