feat: primeira versão
This commit is contained in:
parent
db01b72b49
commit
9e1f642638
33
AdapterWithErrorHandler.cs
Normal file
33
AdapterWithErrorHandler.cs
Normal file
@ -0,0 +1,33 @@
|
||||
using Microsoft.Bot.Builder.Integration.AspNet.Core;
|
||||
using Microsoft.Bot.Builder.TraceExtensions;
|
||||
using Microsoft.Bot.Connector.Authentication;
|
||||
using Microsoft.Bot.Schema;
|
||||
|
||||
namespace IAChat;
|
||||
|
||||
public class AdapterWithErrorHandler : CloudAdapter
|
||||
{
|
||||
public AdapterWithErrorHandler(BotFrameworkAuthentication auth, ILogger<IBotFrameworkHttpAdapter> logger)
|
||||
: base(auth, logger)
|
||||
{
|
||||
OnTurnError = async (turnContext, exception) =>
|
||||
{
|
||||
// Log any leaked exception from the application.
|
||||
// NOTE: In production environment, you should consider logging this to
|
||||
// Azure Application Insights. Visit https://aka.ms/bottelemetry to see how
|
||||
// to add telemetry capture to your bot.
|
||||
logger.LogError(exception, $"[OnTurnError] unhandled error : {exception.Message}");
|
||||
|
||||
// Only send error message for user messages, not for other message types so the bot doesn't spam a channel or chat.
|
||||
if (turnContext.Activity.Type == ActivityTypes.Message)
|
||||
{
|
||||
// Send a message to the user
|
||||
await turnContext.SendActivityAsync("The bot encountered an error or bug.");
|
||||
await turnContext.SendActivityAsync("To continue to run this bot, please fix the bot source code.");
|
||||
|
||||
// Send a trace activity, which will be displayed in the Bot Framework Emulator
|
||||
await turnContext.TraceActivityAsync("OnTurnError Trace", exception.Message, "https://www.botframework.com/schemas/error", "TurnError");
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
62
Bot/ChatIABot.cs
Normal file
62
Bot/ChatIABot.cs
Normal file
@ -0,0 +1,62 @@
|
||||
using IAChat.MSGraph;
|
||||
using Microsoft.Bot.Builder;
|
||||
using Microsoft.Bot.Builder.Teams;
|
||||
using Microsoft.Bot.Schema;
|
||||
using System.Net.Http;
|
||||
using System.Net.Http.Headers;
|
||||
using System.Web;
|
||||
|
||||
namespace IAChat.Bot;
|
||||
|
||||
public class ChatIABot : TeamsActivityHandler
|
||||
{
|
||||
private readonly IHttpClientFactory clientFactory;
|
||||
private readonly TokenManager tokenManager;
|
||||
|
||||
//public ChatIABot(IHttpClientFactory clientFactory, IConfigurationManager configuration)
|
||||
public ChatIABot(IServiceProvider serviceProvider)
|
||||
{
|
||||
this.clientFactory = serviceProvider.GetService<IHttpClientFactory>();
|
||||
this.tokenManager = serviceProvider.GetService<TokenManager>();
|
||||
}
|
||||
protected override async Task OnMessageActivityAsync(ITurnContext<IMessageActivity> turnContext, CancellationToken cancellationToken)
|
||||
{
|
||||
string messageText = turnContext.Activity.RemoveRecipientMention()?.Trim();
|
||||
var userId = turnContext.Activity.From.Id;
|
||||
var userName = turnContext.Activity.From.Name;
|
||||
var tenantId = turnContext.Activity.Conversation.TenantId;
|
||||
var aadObjectId = turnContext.Activity.From.AadObjectId;
|
||||
|
||||
var token = await tokenManager.ObterToken(userId);
|
||||
var replyText = await GetMessage(token, messageText);
|
||||
await turnContext.SendActivityAsync(MessageFactory.Text(replyText), cancellationToken);
|
||||
}
|
||||
|
||||
protected override async Task OnMembersAddedAsync(IList<ChannelAccount> membersAdded, ITurnContext<IConversationUpdateActivity> turnContext, CancellationToken cancellationToken)
|
||||
{
|
||||
var welcomeText = "Olá! Eu sou o Ian. Uma inteligência artificial interna da Domvs iT.\nSe perguntar algo sobre o conteúdo do SahePoint da Domvs, eu conseguirei responder.";
|
||||
foreach (var member in membersAdded)
|
||||
{
|
||||
if (member.Id != turnContext.Activity.Recipient.Id)
|
||||
{
|
||||
await turnContext.SendActivityAsync(MessageFactory.Text(welcomeText), cancellationToken);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private async Task<string> GetMessage(string jwt, string message)
|
||||
{
|
||||
var httpClient = this.clientFactory.CreateClient();
|
||||
var content = "";
|
||||
using (var requestMessage = new HttpRequestMessage(HttpMethod.Get, $"http://localhost:5020/Chat?Message={HttpUtility.UrlEncode(message)}"))
|
||||
{
|
||||
requestMessage.Headers.Authorization = new AuthenticationHeaderValue("Bearer", jwt);
|
||||
|
||||
var responseGet = await httpClient.SendAsync(requestMessage);
|
||||
content = responseGet.Content.ReadAsStringAsync().Result;
|
||||
}
|
||||
|
||||
return content;
|
||||
}
|
||||
}
|
||||
|
||||
8
Config.cs
Normal file
8
Config.cs
Normal file
@ -0,0 +1,8 @@
|
||||
namespace IAChat
|
||||
{
|
||||
public class ConfigOptions
|
||||
{
|
||||
public string BOT_ID { get; set; }
|
||||
public string BOT_PASSWORD { get; set; }
|
||||
}
|
||||
}
|
||||
30
Controllers/BotController.cs
Normal file
30
Controllers/BotController.cs
Normal file
@ -0,0 +1,30 @@
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.Bot.Builder;
|
||||
using Microsoft.Bot.Builder.Integration.AspNet.Core;
|
||||
|
||||
namespace IAChat.Controllers;
|
||||
|
||||
// This ASP Controller is created to handle a request. Dependency Injection will provide the Adapter and IBot
|
||||
// implementation at runtime. Multiple different IBot implementations running at different endpoints can be
|
||||
// achieved by specifying a more specific type for the bot constructor argument.
|
||||
[Route("api/messages")]
|
||||
[ApiController]
|
||||
public class BotController : ControllerBase
|
||||
{
|
||||
private readonly IBotFrameworkHttpAdapter Adapter;
|
||||
private readonly IBot Bot;
|
||||
|
||||
public BotController(IBotFrameworkHttpAdapter adapter, IBot bot)
|
||||
{
|
||||
Adapter = adapter;
|
||||
Bot = bot;
|
||||
}
|
||||
|
||||
[HttpPost, HttpGet]
|
||||
public async Task PostAsync()
|
||||
{
|
||||
// Delegate the processing of the HTTP POST to the adapter.
|
||||
// The adapter will invoke the bot.
|
||||
await Adapter.ProcessAsync(Request, Response, Bot);
|
||||
}
|
||||
}
|
||||
15
IAChat.csproj
Normal file
15
IAChat.csproj
Normal file
@ -0,0 +1,15 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk.Web">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net8.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.AspNet.WebApi.Client" Version="6.0.0" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="6.0.0" />
|
||||
<PackageReference Include="Microsoft.Bot.Builder" Version="4.21.1" />
|
||||
<PackageReference Include="Microsoft.Bot.Builder.Integration.AspNet.Core" Version="4.21.1" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
31
IAChat.sln
Normal file
31
IAChat.sln
Normal file
@ -0,0 +1,31 @@
|
||||
|
||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||
# Visual Studio Version 17
|
||||
VisualStudioVersion = 17.11.35327.3
|
||||
MinimumVisualStudioVersion = 10.0.40219.1
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "IAChat", "IAChat.csproj", "{1E07A203-25BE-4F59-B865-F4A08D776E74}"
|
||||
EndProject
|
||||
Project("{A9E3F50B-275E-4AF7-ADCE-8BE12D41E305}") = "TeamsApp", "TeamsApp\TeamsApp.ttkproj", "{71A41EF5-AC32-4E43-A247-FF63E7F0CF39}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
Release|Any CPU = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{1E07A203-25BE-4F59-B865-F4A08D776E74}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{1E07A203-25BE-4F59-B865-F4A08D776E74}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{1E07A203-25BE-4F59-B865-F4A08D776E74}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{1E07A203-25BE-4F59-B865-F4A08D776E74}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{71A41EF5-AC32-4E43-A247-FF63E7F0CF39}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{71A41EF5-AC32-4E43-A247-FF63E7F0CF39}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{71A41EF5-AC32-4E43-A247-FF63E7F0CF39}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{71A41EF5-AC32-4E43-A247-FF63E7F0CF39}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
EndGlobalSection
|
||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||
SolutionGuid = {1DA1A381-FC1E-44CE-AAD5-E15F6F6BA5CA}
|
||||
EndGlobalSection
|
||||
EndGlobal
|
||||
49
MSGraph/TokenManager.cs
Normal file
49
MSGraph/TokenManager.cs
Normal file
@ -0,0 +1,49 @@
|
||||
using Microsoft.Identity.Client;
|
||||
|
||||
namespace IAChat.MSGraph
|
||||
{
|
||||
public class TokenManager
|
||||
{
|
||||
private readonly IConfiguration _configuration;
|
||||
private readonly string _tenantId;
|
||||
private readonly string _clientId;
|
||||
|
||||
public TokenManager(IConfigurationManager configuration)
|
||||
{
|
||||
_configuration = configuration;
|
||||
_tenantId = _configuration.GetSection("AppTenantId").Value;
|
||||
_clientId = _configuration.GetSection("AppClientID").Value;
|
||||
}
|
||||
|
||||
|
||||
public async Task<string> ObterToken(string userEmail)
|
||||
{
|
||||
// Configuração do contexto de autenticação
|
||||
var app = PublicClientApplicationBuilder
|
||||
.Create(_clientId)
|
||||
.WithAuthority(AzureCloudInstance.AzurePublic, _tenantId)
|
||||
.Build();
|
||||
|
||||
// Definir os escopos necessários
|
||||
string[] scopes = new string[] {
|
||||
"https://graph.microsoft.com/.default",
|
||||
"User.Read"
|
||||
};
|
||||
|
||||
try
|
||||
{
|
||||
var result = await app.AcquireTokenInteractive(scopes)
|
||||
.WithLoginHint(userEmail)
|
||||
.ExecuteAsync();
|
||||
|
||||
return result.AccessToken;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
// Tratamento de erro
|
||||
Console.WriteLine($"Erro ao obter token: {ex.Message}");
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
51
MSGraph/akjkpvjm.5o3~
Normal file
51
MSGraph/akjkpvjm.5o3~
Normal file
@ -0,0 +1,51 @@
|
||||
using Microsoft.Identity.Client;
|
||||
|
||||
namespace IAChat.MSGraph
|
||||
{
|
||||
public class TokenManager
|
||||
{
|
||||
public class GetToken
|
||||
{
|
||||
private readonly IConfiguration _configuration;
|
||||
private readonly string _tenantId;
|
||||
private readonly string _clientId;
|
||||
|
||||
public GetToken(IConfiguration configuration)
|
||||
{
|
||||
_configuration = configuration;
|
||||
_tenantId = _configuration.GetSection("AppTenantId").Value;
|
||||
_clientId = _configuration.GetSection("AppClientID").Value;
|
||||
}
|
||||
|
||||
public async Task<string> ObterTokenParaTeams(string userEmail)
|
||||
{
|
||||
// Configuração do contexto de autenticação
|
||||
var app = PublicClientApplicationBuilder
|
||||
.Create(_clientId)
|
||||
.WithAuthority(AzureCloudInstance.AzurePublic, _tenantId)
|
||||
.Build();
|
||||
|
||||
// Definir os escopos necessários
|
||||
string[] scopes = new string[] {
|
||||
"https://graph.microsoft.com/.default",
|
||||
"User.Read"
|
||||
};
|
||||
|
||||
try
|
||||
{
|
||||
var result = await app.AcquireTokenInteractive(scopes)
|
||||
.WithLoginHint(userEmail)
|
||||
.ExecuteAsync();
|
||||
|
||||
return result.AccessToken;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
// Tratamento de erro
|
||||
Console.WriteLine($"Erro ao obter token: {ex.Message}");
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
49
Program.cs
Normal file
49
Program.cs
Normal file
@ -0,0 +1,49 @@
|
||||
using IAChat;
|
||||
using IAChat.Bot;
|
||||
using IAChat.MSGraph;
|
||||
using Microsoft.Bot.Builder;
|
||||
using Microsoft.Bot.Builder.Integration.AspNet.Core;
|
||||
using Microsoft.Bot.Connector.Authentication;
|
||||
|
||||
var builder = WebApplication.CreateBuilder(args);
|
||||
|
||||
builder.Services.AddControllers();
|
||||
builder.Services.AddHttpClient("WebClient", client => client.Timeout = TimeSpan.FromSeconds(600));
|
||||
builder.Services.AddHttpContextAccessor();
|
||||
|
||||
builder.Services.AddHttpClient();
|
||||
|
||||
// Create the Bot Framework Authentication to be used with the Bot Adapter.
|
||||
var config = builder.Configuration.Get<ConfigOptions>();
|
||||
builder.Configuration["MicrosoftAppType"] = "MultiTenant";
|
||||
builder.Configuration["MicrosoftAppId"] = config.BOT_ID;
|
||||
builder.Configuration["MicrosoftAppPassword"] = config.BOT_PASSWORD;
|
||||
builder.Services.AddSingleton<BotFrameworkAuthentication, ConfigurationBotFrameworkAuthentication>();
|
||||
builder.Services.AddSingleton<IConfigurationManager>(builder.Configuration);
|
||||
builder.Services.AddScoped<TokenManager>();
|
||||
|
||||
// Create the Bot Framework Adapter with error handling enabled.
|
||||
builder.Services.AddSingleton<IBotFrameworkHttpAdapter, AdapterWithErrorHandler>();
|
||||
|
||||
// Create the bot as a transient. In this case the ASP Controller is expecting an IBot.
|
||||
builder.Services.AddTransient<IBot, ChatIABot>();
|
||||
|
||||
var app = builder.Build();
|
||||
|
||||
if (app.Environment.IsDevelopment())
|
||||
{
|
||||
app.UseDeveloperExceptionPage();
|
||||
}
|
||||
app.UseStaticFiles();
|
||||
|
||||
app.UseRouting();
|
||||
|
||||
//app.UseAuthentication();
|
||||
//app.UseAuthorization();
|
||||
|
||||
app.UseEndpoints(endpoints =>
|
||||
{
|
||||
endpoints.MapControllers();
|
||||
});
|
||||
|
||||
app.Run();
|
||||
25
Properties/launchSettings.json
Normal file
25
Properties/launchSettings.json
Normal file
@ -0,0 +1,25 @@
|
||||
{
|
||||
"profiles": {
|
||||
// Debug project within Teams
|
||||
"Start Project": {
|
||||
"commandName": "Project",
|
||||
"dotnetRunMessages": true,
|
||||
"applicationUrl": "http://localhost:5130",
|
||||
"environmentVariables": {
|
||||
"ASPNETCORE_ENVIRONMENT": "Development"
|
||||
},
|
||||
"hotReloadProfile": "aspnetcore"
|
||||
},
|
||||
// Debug project within Teams App Test Tool
|
||||
"Teams App Test Tool": {
|
||||
"commandName": "Project",
|
||||
"dotnetRunMessages": true,
|
||||
"applicationUrl": "http://localhost:5130",
|
||||
"environmentVariables": {
|
||||
"ASPNETCORE_ENVIRONMENT": "TestTool",
|
||||
"TEAMSFX_NOTIFICATION_STORE_FILENAME": ".notification.testtoolstore.json"
|
||||
},
|
||||
"hotReloadProfile": "aspnetcore"
|
||||
},
|
||||
}
|
||||
}
|
||||
28
TeamsApp/README.md
Normal file
28
TeamsApp/README.md
Normal file
@ -0,0 +1,28 @@
|
||||
# Welcome to Teams Toolkit!
|
||||
|
||||
## Quick Start
|
||||
1. In the debug dropdown menu, select Dev Tunnels > Create A Tunnel (set authentication type to Public) or select an existing public dev tunnel
|
||||
</br>
|
||||
2. Right-click the 'TeamsApp' project in Solution Explorer and select Teams Toolkit > Prepare Teams App Dependencies
|
||||
3. If prompted, sign in to Visual Studio with a Microsoft 365 work or school account
|
||||
4. Press F5, or select Debug > Start Debugging menu in Visual Studio to start your app
|
||||
</br>
|
||||
5. In the opened web browser, select Add button to test the app in Teams
|
||||
6. In the message input field, type and send anything to your bot to get a response
|
||||
|
||||
## Debug in Test Tool
|
||||
Teams App Test Tool allows developers test and debug bots locally without needing Microsoft 365 accounts, development tunnels, or Teams app and bot registration. See https://aka.ms/teams-toolkit-vs-test-tool for more details.
|
||||
|
||||
## Run the app on other platforms
|
||||
|
||||
The Teams app can run in other platforms like Outlook and Microsoft 365 app. See https://aka.ms/vs-ttk-debug-multi-profiles for more details.
|
||||
|
||||
## Get more info
|
||||
|
||||
New to Teams app development or Teams Toolkit? Explore Teams app manifests, cloud deployment, and much more in the https://aka.ms/teams-toolkit-vs-docs.
|
||||
|
||||
## Report an issue
|
||||
|
||||
Select Visual Studio > Help > Send Feedback > Report a Problem.
|
||||
Or, create an issue directly in our GitHub repository:
|
||||
https://github.com/OfficeDev/TeamsFx/issues
|
||||
9
TeamsApp/TeamsApp.ttkproj
Normal file
9
TeamsApp/TeamsApp.ttkproj
Normal file
@ -0,0 +1,9 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="15.0" Sdk="Microsoft.TeamsFx.Sdk">
|
||||
<PropertyGroup Label="Globals">
|
||||
<ProjectGuid>71a41ef5-ac32-4e43-a247-ff63e7f0cf39</ProjectGuid>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<ProjectCapability Include="ProjectConfigurationsDeclaredDimensions" />
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
BIN
TeamsApp/appPackage/color.png
Normal file
BIN
TeamsApp/appPackage/color.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 5.0 KiB |
46
TeamsApp/appPackage/manifest - Copy.json
Normal file
46
TeamsApp/appPackage/manifest - Copy.json
Normal file
@ -0,0 +1,46 @@
|
||||
{
|
||||
"$schema": "https://developer.microsoft.com/en-us/json-schemas/teams/v1.17/MicrosoftTeams.schema.json",
|
||||
"manifestVersion": "1.17",
|
||||
"version": "1.0.0",
|
||||
"id": "${{TEAMS_APP_ID}}",
|
||||
"developer": {
|
||||
"name": "Teams App, Inc.",
|
||||
"websiteUrl": "https://www.example.com",
|
||||
"privacyUrl": "https://www.example.com/privacy",
|
||||
"termsOfUseUrl": "https://www.example.com/termofuse"
|
||||
},
|
||||
"icons": {
|
||||
"color": "color.png",
|
||||
"outline": "outline.png"
|
||||
},
|
||||
"name": {
|
||||
"short": "IAChat${{APP_NAME_SUFFIX}}",
|
||||
"full": "full name for IAChat"
|
||||
},
|
||||
"description": {
|
||||
"short": "Short description of IAChat",
|
||||
"full": "Full description of IAChat"
|
||||
},
|
||||
"accentColor": "#FFFFFF",
|
||||
"bots": [
|
||||
{
|
||||
"botId": "${{BOT_ID}}",
|
||||
"scopes": [
|
||||
"personal",
|
||||
"team",
|
||||
"groupChat"
|
||||
],
|
||||
"supportsFiles": false,
|
||||
"isNotificationOnly": false
|
||||
}
|
||||
],
|
||||
"composeExtensions": [
|
||||
],
|
||||
"configurableTabs": [],
|
||||
"staticTabs": [],
|
||||
"permissions": [
|
||||
"identity",
|
||||
"messageTeamMembers"
|
||||
],
|
||||
"validDomains": []
|
||||
}
|
||||
46
TeamsApp/appPackage/manifest.json
Normal file
46
TeamsApp/appPackage/manifest.json
Normal file
@ -0,0 +1,46 @@
|
||||
{
|
||||
"$schema": "https://developer.microsoft.com/en-us/json-schemas/teams/v1.17/MicrosoftTeams.schema.json",
|
||||
"manifestVersion": "1.17",
|
||||
"version": "1.0.0",
|
||||
"id": "${{TEAMS_APP_ID}}",
|
||||
"developer": {
|
||||
"name": "Jobmaker.com.br",
|
||||
"websiteUrl": "https://jobmaker.com.br",
|
||||
"privacyUrl": "https://jobmaker.com.br/privacy",
|
||||
"termsOfUseUrl": "https://jobmaker.com.br/termofuse"
|
||||
},
|
||||
"icons": {
|
||||
"color": "technical-support192.png",
|
||||
"outline": "outline.png"
|
||||
},
|
||||
"name": {
|
||||
"short": "Ian - ${{APP_NAME_SUFFIX}}",
|
||||
"full": "Ian é um robô com inteligência artificial para realizar tarefas internas à Domvs iT"
|
||||
},
|
||||
"description": {
|
||||
"short": "Ian é um robô interno Domvs iT",
|
||||
"full": "Ian é um robô com inteligência artificial para realizar tarefas internas à Domvs iT"
|
||||
},
|
||||
"accentColor": "#FFFFFF",
|
||||
"bots": [
|
||||
{
|
||||
"botId": "${{BOT_ID}}",
|
||||
"scopes": [
|
||||
"personal",
|
||||
"team",
|
||||
"groupChat"
|
||||
],
|
||||
"supportsFiles": false,
|
||||
"isNotificationOnly": false
|
||||
}
|
||||
],
|
||||
"composeExtensions": [
|
||||
],
|
||||
"configurableTabs": [],
|
||||
"staticTabs": [],
|
||||
"permissions": [
|
||||
"identity",
|
||||
"messageTeamMembers"
|
||||
],
|
||||
"validDomains": []
|
||||
}
|
||||
46
TeamsApp/appPackage/manifest.json~RFc8742a7.TMP
Normal file
46
TeamsApp/appPackage/manifest.json~RFc8742a7.TMP
Normal file
@ -0,0 +1,46 @@
|
||||
{
|
||||
"$schema": "https://developer.microsoft.com/en-us/json-schemas/teams/v1.17/MicrosoftTeams.schema.json",
|
||||
"manifestVersion": "1.17",
|
||||
"version": "1.0.0",
|
||||
"id": "${{TEAMS_APP_ID}}",
|
||||
"developer": {
|
||||
"name": "Jobmaker.com.br",
|
||||
"websiteUrl": "https://jobmaker.com.br",
|
||||
"privacyUrl": "https://jobmaker.com.br/privacy",
|
||||
"termsOfUseUrl": "https://jobmaker.com.br/termofuse"
|
||||
},
|
||||
"icons": {
|
||||
"color": "color.png",
|
||||
"outline": "technical-support32.png"
|
||||
},
|
||||
"name": {
|
||||
"short": "Ian - ${{APP_NAME_SUFFIX}}",
|
||||
"full": "Ian é um robô com inteligência artificial para realizar tarefas internas à Domvs iT"
|
||||
},
|
||||
"description": {
|
||||
"short": "Ian é um robô com inteligência artificial para realizar tarefas internas à Domvs iT",
|
||||
"full": "Ian é um robô com inteligência artificial para realizar tarefas internas à Domvs iT"
|
||||
},
|
||||
"accentColor": "#FFFFFF",
|
||||
"bots": [
|
||||
{
|
||||
"botId": "${{BOT_ID}}",
|
||||
"scopes": [
|
||||
"personal",
|
||||
"team",
|
||||
"groupChat"
|
||||
],
|
||||
"supportsFiles": false,
|
||||
"isNotificationOnly": false
|
||||
}
|
||||
],
|
||||
"composeExtensions": [
|
||||
],
|
||||
"configurableTabs": [],
|
||||
"staticTabs": [],
|
||||
"permissions": [
|
||||
"identity",
|
||||
"messageTeamMembers"
|
||||
],
|
||||
"validDomains": []
|
||||
}
|
||||
46
TeamsApp/appPackage/manifest.json~RFc97232b.TMP
Normal file
46
TeamsApp/appPackage/manifest.json~RFc97232b.TMP
Normal file
@ -0,0 +1,46 @@
|
||||
{
|
||||
"$schema": "https://developer.microsoft.com/en-us/json-schemas/teams/v1.17/MicrosoftTeams.schema.json",
|
||||
"manifestVersion": "1.17",
|
||||
"version": "1.0.0",
|
||||
"id": "${{TEAMS_APP_ID}}",
|
||||
"developer": {
|
||||
"name": "Jobmaker.com.br",
|
||||
"websiteUrl": "https://jobmaker.com.br",
|
||||
"privacyUrl": "https://jobmaker.com.br/privacy",
|
||||
"termsOfUseUrl": "https://jobmaker.com.br/termofuse"
|
||||
},
|
||||
"icons": {
|
||||
"color": "technical-support192.png",
|
||||
"outline": "technical-support32.png"
|
||||
},
|
||||
"name": {
|
||||
"short": "Ian - ${{APP_NAME_SUFFIX}}",
|
||||
"full": "Ian é um robô com inteligência artificial para realizar tarefas internas à Domvs iT"
|
||||
},
|
||||
"description": {
|
||||
"short": "Ian é um robô interno Domvs iT",
|
||||
"full": "Ian é um robô com inteligência artificial para realizar tarefas internas à Domvs iT"
|
||||
},
|
||||
"accentColor": "#FFFFFF",
|
||||
"bots": [
|
||||
{
|
||||
"botId": "${{BOT_ID}}",
|
||||
"scopes": [
|
||||
"personal",
|
||||
"team",
|
||||
"groupChat"
|
||||
],
|
||||
"supportsFiles": false,
|
||||
"isNotificationOnly": false
|
||||
}
|
||||
],
|
||||
"composeExtensions": [
|
||||
],
|
||||
"configurableTabs": [],
|
||||
"staticTabs": [],
|
||||
"permissions": [
|
||||
"identity",
|
||||
"messageTeamMembers"
|
||||
],
|
||||
"validDomains": []
|
||||
}
|
||||
BIN
TeamsApp/appPackage/outline.png
Normal file
BIN
TeamsApp/appPackage/outline.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 327 B |
BIN
TeamsApp/appPackage/technical-support192.png
Normal file
BIN
TeamsApp/appPackage/technical-support192.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 10 KiB |
BIN
TeamsApp/appPackage/technical-support32.png
Normal file
BIN
TeamsApp/appPackage/technical-support32.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.7 KiB |
BIN
TeamsApp/appPackage/technical-support32n.png
Normal file
BIN
TeamsApp/appPackage/technical-support32n.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.7 KiB |
15
TeamsApp/env/.env.dev
vendored
Normal file
15
TeamsApp/env/.env.dev
vendored
Normal file
@ -0,0 +1,15 @@
|
||||
# This file includes environment variables that will be committed to git by default.
|
||||
|
||||
# Built-in environment variables
|
||||
TEAMSFX_ENV=dev
|
||||
APP_NAME_SUFFIX=dev
|
||||
|
||||
# Updating AZURE_SUBSCRIPTION_ID or AZURE_RESOURCE_GROUP_NAME after provision may also require an update to RESOURCE_SUFFIX, because some services require a globally unique name across subscriptions/resource groups.
|
||||
AZURE_SUBSCRIPTION_ID=
|
||||
AZURE_RESOURCE_GROUP_NAME=
|
||||
RESOURCE_SUFFIX=
|
||||
|
||||
# Generated during provision, you can also add your own variables.
|
||||
BOT_ID=
|
||||
TEAMS_APP_ID=
|
||||
BOT_AZURE_APP_SERVICE_RESOURCE_ID=
|
||||
16
TeamsApp/env/.env.local
vendored
Normal file
16
TeamsApp/env/.env.local
vendored
Normal file
@ -0,0 +1,16 @@
|
||||
# This file includes environment variables that can be committed to git. It's gitignored by default because it represents your local development environment.
|
||||
|
||||
# Built-in environment variables
|
||||
TEAMSFX_ENV=local
|
||||
APP_NAME_SUFFIX=local
|
||||
|
||||
# Generated during provision, you can also add your own variables.
|
||||
BOT_ID=8f4248fc-ee30-4f54-8793-66edcca3fd20
|
||||
TEAMS_APP_ID=ea0047b8-d686-4e93-b987-d2c039d7d0ef
|
||||
TEAMS_APP_TENANT_ID=20190830-5fd4-4a72-b8fd-1c1cb35b25bc
|
||||
BOT_OBJECT_ID=76009812-3d88-43a2-97c6-3920e1ad2223
|
||||
BOT_ENDPOINT=https://vrzg2z27-5130.brs.devtunnels.ms
|
||||
BOT_DOMAIN=vrzg2z27-5130.brs.devtunnels.ms
|
||||
|
||||
|
||||
TEAMSFX_M365_USER_NAME=ricardo.carneiro@domvsit.com.br
|
||||
73
TeamsApp/infra/azure.bicep
Normal file
73
TeamsApp/infra/azure.bicep
Normal file
@ -0,0 +1,73 @@
|
||||
@maxLength(20)
|
||||
@minLength(4)
|
||||
@description('Used to generate names for all resources in this file')
|
||||
param resourceBaseName string
|
||||
|
||||
@description('Required when create Azure Bot service')
|
||||
param botAadAppClientId string
|
||||
|
||||
@secure()
|
||||
@description('Required by Bot Framework package in your bot project')
|
||||
param botAadAppClientSecret string
|
||||
|
||||
param webAppSKU string
|
||||
|
||||
@maxLength(42)
|
||||
param botDisplayName string
|
||||
|
||||
param serverfarmsName string = resourceBaseName
|
||||
param webAppName string = resourceBaseName
|
||||
param location string = resourceGroup().location
|
||||
|
||||
// Compute resources for your Web App
|
||||
resource serverfarm 'Microsoft.Web/serverfarms@2021-02-01' = {
|
||||
kind: 'app'
|
||||
location: location
|
||||
name: serverfarmsName
|
||||
sku: {
|
||||
name: webAppSKU
|
||||
}
|
||||
}
|
||||
|
||||
// Web App that hosts your bot
|
||||
resource webApp 'Microsoft.Web/sites@2021-02-01' = {
|
||||
kind: 'app'
|
||||
location: location
|
||||
name: webAppName
|
||||
properties: {
|
||||
serverFarmId: serverfarm.id
|
||||
httpsOnly: true
|
||||
siteConfig: {
|
||||
appSettings: [
|
||||
{
|
||||
name: 'WEBSITE_RUN_FROM_PACKAGE'
|
||||
value: '1'
|
||||
}
|
||||
{
|
||||
name: 'BOT_ID'
|
||||
value: botAadAppClientId
|
||||
}
|
||||
{
|
||||
name: 'BOT_PASSWORD'
|
||||
value: botAadAppClientSecret
|
||||
}
|
||||
]
|
||||
ftpsState: 'FtpsOnly'
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Register your web service as a bot with the Bot Framework
|
||||
module azureBotRegistration './botRegistration/azurebot.bicep' = {
|
||||
name: 'Azure-Bot-registration'
|
||||
params: {
|
||||
resourceBaseName: resourceBaseName
|
||||
botAadAppClientId: botAadAppClientId
|
||||
botAppDomain: webApp.properties.defaultHostName
|
||||
botDisplayName: botDisplayName
|
||||
}
|
||||
}
|
||||
|
||||
// The output will be persisted in .env.{envName}. Visit https://aka.ms/teamsfx-actions/arm-deploy for more details.
|
||||
output BOT_AZURE_APP_SERVICE_RESOURCE_ID string = webApp.id
|
||||
output BOT_DOMAIN string = webApp.properties.defaultHostName
|
||||
21
TeamsApp/infra/azure.parameters.json
Normal file
21
TeamsApp/infra/azure.parameters.json
Normal file
@ -0,0 +1,21 @@
|
||||
{
|
||||
"$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentParameters.json#",
|
||||
"contentVersion": "1.0.0.0",
|
||||
"parameters": {
|
||||
"resourceBaseName": {
|
||||
"value": "bot${{RESOURCE_SUFFIX}}"
|
||||
},
|
||||
"botAadAppClientId": {
|
||||
"value": "${{BOT_ID}}"
|
||||
},
|
||||
"botAadAppClientSecret": {
|
||||
"value": "${{SECRET_BOT_PASSWORD}}"
|
||||
},
|
||||
"webAppSKU": {
|
||||
"value": "B1"
|
||||
},
|
||||
"botDisplayName": {
|
||||
"value": "IAChat"
|
||||
}
|
||||
}
|
||||
}
|
||||
37
TeamsApp/infra/botRegistration/azurebot.bicep
Normal file
37
TeamsApp/infra/botRegistration/azurebot.bicep
Normal file
@ -0,0 +1,37 @@
|
||||
@maxLength(20)
|
||||
@minLength(4)
|
||||
@description('Used to generate names for all resources in this file')
|
||||
param resourceBaseName string
|
||||
|
||||
@maxLength(42)
|
||||
param botDisplayName string
|
||||
|
||||
param botServiceName string = resourceBaseName
|
||||
param botServiceSku string = 'F0'
|
||||
param botAadAppClientId string
|
||||
param botAppDomain string
|
||||
|
||||
// Register your web service as a bot with the Bot Framework
|
||||
resource botService 'Microsoft.BotService/botServices@2021-03-01' = {
|
||||
kind: 'azurebot'
|
||||
location: 'global'
|
||||
name: botServiceName
|
||||
properties: {
|
||||
displayName: botDisplayName
|
||||
endpoint: 'https://${botAppDomain}/api/messages'
|
||||
msaAppId: botAadAppClientId
|
||||
}
|
||||
sku: {
|
||||
name: botServiceSku
|
||||
}
|
||||
}
|
||||
|
||||
// Connect the bot service to Microsoft Teams
|
||||
resource botServiceMsTeamsChannel 'Microsoft.BotService/botServices/channels@2021-03-01' = {
|
||||
parent: botService
|
||||
location: 'global'
|
||||
name: 'MsTeamsChannel'
|
||||
properties: {
|
||||
channelName: 'MsTeamsChannel'
|
||||
}
|
||||
}
|
||||
1
TeamsApp/infra/botRegistration/readme.md
Normal file
1
TeamsApp/infra/botRegistration/readme.md
Normal file
@ -0,0 +1 @@
|
||||
The `azurebot.bicep` module is provided to help you create Azure Bot service when you don't use Azure to host your app. If you use Azure as infrastrcture for your app, `azure.bicep` under infra folder already leverages this module to create Azure Bot service for you. You don't need to deploy `azurebot.bicep` again.
|
||||
15
TeamsApp/launchSettings.json
Normal file
15
TeamsApp/launchSettings.json
Normal file
@ -0,0 +1,15 @@
|
||||
{
|
||||
"profiles": {
|
||||
// Launch project within Teams
|
||||
"Microsoft Teams (browser)": {
|
||||
"commandName": "Project",
|
||||
"launchUrl": "https://teams.microsoft.com/l/app/${{TEAMS_APP_ID}}?installAppPackage=true&webjoin=true&appTenantId=${{TEAMS_APP_TENANT_ID}}&login_hint=${{TEAMSFX_M365_USER_NAME}}",
|
||||
},
|
||||
// Launch project within Teams App Test Tool
|
||||
"Teams App Test Tool (browser)": {
|
||||
"commandName": "Project",
|
||||
"launchTestTool": true,
|
||||
"launchUrl": "http://localhost:56150",
|
||||
},
|
||||
}
|
||||
}
|
||||
74
TeamsApp/teamsapp.local.yml
Normal file
74
TeamsApp/teamsapp.local.yml
Normal file
@ -0,0 +1,74 @@
|
||||
# yaml-language-server: $schema=https://aka.ms/teams-toolkit/v1.5/yaml.schema.json
|
||||
# Visit https://aka.ms/teamsfx-v5.0-guide for details on this file
|
||||
# Visit https://aka.ms/teamsfx-actions for details on actions
|
||||
version: v1.5
|
||||
|
||||
provision:
|
||||
# Creates a Teams app
|
||||
- uses: teamsApp/create
|
||||
with:
|
||||
# Teams app name
|
||||
name: IAChat${{APP_NAME_SUFFIX}}
|
||||
# Write the information of created resources into environment file for
|
||||
# the specified environment variable(s).
|
||||
writeToEnvironmentFile:
|
||||
teamsAppId: TEAMS_APP_ID
|
||||
|
||||
# Create or reuse an existing Microsoft Entra application for bot.
|
||||
- uses: aadApp/create
|
||||
with:
|
||||
# The Microsoft Entra application's display name
|
||||
name: IAChat${{APP_NAME_SUFFIX}}
|
||||
generateClientSecret: true
|
||||
signInAudience: AzureADMultipleOrgs
|
||||
writeToEnvironmentFile:
|
||||
# The Microsoft Entra application's client id created for bot.
|
||||
clientId: BOT_ID
|
||||
# The Microsoft Entra application's client secret created for bot.
|
||||
clientSecret: SECRET_BOT_PASSWORD
|
||||
# The Microsoft Entra application's object id created for bot.
|
||||
objectId: BOT_OBJECT_ID
|
||||
|
||||
# Generate runtime appsettings to JSON file
|
||||
- uses: file/createOrUpdateJsonFile
|
||||
with:
|
||||
target: ../appsettings.Development.json
|
||||
content:
|
||||
BOT_ID: ${{BOT_ID}}
|
||||
BOT_PASSWORD: ${{SECRET_BOT_PASSWORD}}
|
||||
|
||||
# Create or update the bot registration on dev.botframework.com
|
||||
- uses: botFramework/create
|
||||
with:
|
||||
botId: ${{BOT_ID}}
|
||||
name: IAChat
|
||||
messagingEndpoint: ${{BOT_ENDPOINT}}/api/messages
|
||||
description: ""
|
||||
channels:
|
||||
- name: msteams
|
||||
|
||||
# Validate using manifest schema
|
||||
- uses: teamsApp/validateManifest
|
||||
with:
|
||||
# Path to manifest template
|
||||
manifestPath: ./appPackage/manifest.json
|
||||
# Build Teams app package with latest env value
|
||||
- uses: teamsApp/zipAppPackage
|
||||
with:
|
||||
# Path to manifest template
|
||||
manifestPath: ./appPackage/manifest.json
|
||||
outputZipPath: ./appPackage/build/appPackage.${{TEAMSFX_ENV}}.zip
|
||||
outputJsonPath: ./appPackage/build/manifest.${{TEAMSFX_ENV}}.json
|
||||
# Validate app package using validation rules
|
||||
- uses: teamsApp/validateAppPackage
|
||||
with:
|
||||
# Relative path to this file. This is the path for built zip file.
|
||||
appPackagePath: ./appPackage/build/appPackage.${{TEAMSFX_ENV}}.zip
|
||||
|
||||
# Apply the Teams app manifest to an existing Teams app in
|
||||
# Teams Developer Portal.
|
||||
# Will use the app id in manifest file to determine which Teams app to update.
|
||||
- uses: teamsApp/update
|
||||
with:
|
||||
# Relative path to this file. This is the path for built zip file.
|
||||
appPackagePath: ./appPackage/build/appPackage.${{TEAMSFX_ENV}}.zip
|
||||
103
TeamsApp/teamsapp.yml
Normal file
103
TeamsApp/teamsapp.yml
Normal file
@ -0,0 +1,103 @@
|
||||
# yaml-language-server: $schema=https://aka.ms/teams-toolkit/v1.5/yaml.schema.json
|
||||
# Visit https://aka.ms/teamsfx-v5.0-guide for details on this file
|
||||
# Visit https://aka.ms/teamsfx-actions for details on actions
|
||||
version: v1.5
|
||||
|
||||
environmentFolderPath: ./env
|
||||
|
||||
# Triggered when 'teamsapp provision' is executed
|
||||
provision:
|
||||
# Creates a Teams app
|
||||
- uses: teamsApp/create
|
||||
with:
|
||||
# Teams app name
|
||||
name: IAChat${{APP_NAME_SUFFIX}}
|
||||
# Write the information of created resources into environment file for
|
||||
# the specified environment variable(s).
|
||||
writeToEnvironmentFile:
|
||||
teamsAppId: TEAMS_APP_ID
|
||||
|
||||
# Create or reuse an existing Microsoft Entra application for bot.
|
||||
- uses: aadApp/create
|
||||
with:
|
||||
# The Microsoft Entra application's display name
|
||||
name: IAChat${{APP_NAME_SUFFIX}}
|
||||
generateClientSecret: true
|
||||
signInAudience: AzureADMultipleOrgs
|
||||
writeToEnvironmentFile:
|
||||
# The Microsoft Entra application's client id created for bot.
|
||||
clientId: BOT_ID
|
||||
# The Microsoft Entra application's client secret created for bot.
|
||||
clientSecret: SECRET_BOT_PASSWORD
|
||||
# The Microsoft Entra application's object id created for bot.
|
||||
objectId: BOT_OBJECT_ID
|
||||
|
||||
- uses: arm/deploy # Deploy given ARM templates parallelly.
|
||||
with:
|
||||
# AZURE_SUBSCRIPTION_ID is a built-in environment variable,
|
||||
# if its value is empty, TeamsFx will prompt you to select a subscription.
|
||||
# Referencing other environment variables with empty values
|
||||
# will skip the subscription selection prompt.
|
||||
subscriptionId: ${{AZURE_SUBSCRIPTION_ID}}
|
||||
# AZURE_RESOURCE_GROUP_NAME is a built-in environment variable,
|
||||
# if its value is empty, TeamsFx will prompt you to select or create one
|
||||
# resource group.
|
||||
# Referencing other environment variables with empty values
|
||||
# will skip the resource group selection prompt.
|
||||
resourceGroupName: ${{AZURE_RESOURCE_GROUP_NAME}}
|
||||
templates:
|
||||
- path: ./infra/azure.bicep # Relative path to this file
|
||||
# Relative path to this yaml file.
|
||||
# Placeholders will be replaced with corresponding environment
|
||||
# variable before ARM deployment.
|
||||
parameters: ./infra/azure.parameters.json
|
||||
# Required when deploying ARM template
|
||||
deploymentName: Create-resources-for-bot
|
||||
# Teams Toolkit will download this bicep CLI version from github for you,
|
||||
# will use bicep CLI in PATH if you remove this config.
|
||||
bicepCliVersion: v0.9.1
|
||||
|
||||
# Validate using manifest schema
|
||||
- uses: teamsApp/validateManifest
|
||||
with:
|
||||
# Path to manifest template
|
||||
manifestPath: ./appPackage/manifest.json
|
||||
# Build Teams app package with latest env value
|
||||
- uses: teamsApp/zipAppPackage
|
||||
with:
|
||||
# Path to manifest template
|
||||
manifestPath: ./appPackage/manifest.json
|
||||
outputZipPath: ./appPackage/build/appPackage.${{TEAMSFX_ENV}}.zip
|
||||
outputJsonPath: ./appPackage/build/manifest.${{TEAMSFX_ENV}}.json
|
||||
# Validate app package using validation rules
|
||||
- uses: teamsApp/validateAppPackage
|
||||
with:
|
||||
# Relative path to this file. This is the path for built zip file.
|
||||
appPackagePath: ./appPackage/build/appPackage.${{TEAMSFX_ENV}}.zip
|
||||
# Apply the Teams app manifest to an existing Teams app in
|
||||
# Teams Developer Portal.
|
||||
# Will use the app id in manifest file to determine which Teams app to update.
|
||||
- uses: teamsApp/update
|
||||
with:
|
||||
# Relative path to this file. This is the path for built zip file.
|
||||
appPackagePath: ./appPackage/build/appPackage.${{TEAMSFX_ENV}}.zip
|
||||
|
||||
# Triggered when 'teamsapp deploy' is executed
|
||||
deploy:
|
||||
- uses: cli/runDotnetCommand
|
||||
with:
|
||||
args: publish --configuration Release IAChat.csproj
|
||||
workingDirectory: ..
|
||||
# Deploy your application to Azure App Service using the zip deploy feature.
|
||||
# For additional details, refer to https://aka.ms/zip-deploy-to-app-services.
|
||||
- uses: azureAppService/zipDeploy
|
||||
with:
|
||||
# Deploy base folder
|
||||
artifactFolder: bin/Release/net8.0/publish
|
||||
# The resource id of the cloud resource to be deployed to.
|
||||
# This key will be generated by arm/deploy action automatically.
|
||||
# You can replace it with your existing Azure Resource id
|
||||
# or add it to your environment variable file.
|
||||
resourceId: ${{BOT_AZURE_APP_SERVICE_RESOURCE_ID}}
|
||||
workingDirectory: ..
|
||||
projectId: a0e11721-e5ae-4dbd-8047-057a772737e7
|
||||
12
appsettings.TestTool.json
Normal file
12
appsettings.TestTool.json
Normal file
@ -0,0 +1,12 @@
|
||||
{
|
||||
"Logging": {
|
||||
"LogLevel": {
|
||||
"Default": "Information",
|
||||
"Microsoft": "Warning",
|
||||
"Microsoft.Hosting.Lifetime": "Information"
|
||||
}
|
||||
},
|
||||
"AllowedHosts": "*",
|
||||
"BOT_ID": "",
|
||||
"BOT_PASSWORD": ""
|
||||
}
|
||||
16
appsettings.json
Normal file
16
appsettings.json
Normal file
@ -0,0 +1,16 @@
|
||||
{
|
||||
"Logging": {
|
||||
"LogLevel": {
|
||||
"Default": "Information",
|
||||
"Microsoft": "Warning",
|
||||
"Microsoft.Hosting.Lifetime": "Information"
|
||||
}
|
||||
},
|
||||
"AllowedHosts": "*",
|
||||
"BOT_ID": "$botId$",
|
||||
"BOT_PASSWORD": "$bot-password$",
|
||||
"AppClientID": "8f4248fc-ee30-4f54-8793-66edcca3fd20",
|
||||
"AppClientSecret": "4ea5e989-37dc-4ace-96a6-0fa0f74ef059",
|
||||
"AppClientSecretValue": "AMI8Q~YCMY4ffjypwWMxOQlDI9I3TCkk3Lhfga8e",
|
||||
"AppTenantId": "20190830-5fd4-4a72-b8fd-1c1cb35b25bc"
|
||||
}
|
||||
Loading…
Reference in New Issue
Block a user