From c72767ff01d2d9c27f8b371b694c18f3f3975e13 Mon Sep 17 00:00:00 2001 From: Ricardo Carneiro Date: Fri, 27 Dec 2024 17:41:43 -0300 Subject: [PATCH] feat: first version with code --- .dockerignore | 30 +++ AdapterWithErrorHandler.cs | 33 ++++ Bot/ChatIABot.cs | 171 ++++++++++++++++++ Comm/ApiService.cs | 91 ++++++++++ Config.cs | 8 + Controllers/BotController.cs | 37 ++++ Dockerfile | 29 +++ DomvsChatBot.csproj | 17 ++ DomvsChatBot.sln | 31 ++++ LocalData/LocalStorage.cs | 11 ++ MSGraph/TokenManager.cs | 116 ++++++++++++ MSGraph/akjkpvjm.5o3~ | 51 ++++++ Program.cs | 61 +++++++ .../registry.redecarneir.us.pubxml | 18 ++ Properties/launchSettings.json | 32 ++++ PushContainer.bat | 4 + TeamsApp/README.md | 28 +++ TeamsApp/TeamsApp.ttkproj | 12 ++ TeamsApp/appPackage.stg.zip | Bin 0 -> 11653 bytes TeamsApp/appPackage/color.png | Bin 0 -> 5131 bytes TeamsApp/appPackage/manifest.json | 46 +++++ TeamsApp/appPackage/manifest.stg.json | 46 +++++ TeamsApp/appPackage/outline.png | Bin 0 -> 327 bytes TeamsApp/appPackage/technical-support192.png | Bin 0 -> 10310 bytes TeamsApp/appPackage/technical-support32.png | Bin 0 -> 1703 bytes TeamsApp/appPackage/technical-support32n.png | Bin 0 -> 1703 bytes TeamsApp/env/.env.dev | 16 ++ TeamsApp/env/.env.local | 19 ++ TeamsApp/env/.env.prod | 18 ++ TeamsApp/env/.env.stg | 19 ++ TeamsApp/infra/azure.bicep | 73 ++++++++ TeamsApp/infra/azure.parameters.json | 21 +++ TeamsApp/infra/botRegistration/azurebot.bicep | 37 ++++ TeamsApp/infra/botRegistration/readme.md | 1 + TeamsApp/launchSettings.json | 15 ++ TeamsApp/teamsapp.local.yml | 74 ++++++++ TeamsApp/teamsapp.stg.yml | 74 ++++++++ TeamsApp/teamsapp.yml | 103 +++++++++++ appsettings.TestTool.json | 12 ++ appsettings.json | 17 ++ 40 files changed, 1371 insertions(+) create mode 100644 .dockerignore create mode 100644 AdapterWithErrorHandler.cs create mode 100644 Bot/ChatIABot.cs create mode 100644 Comm/ApiService.cs create mode 100644 Config.cs create mode 100644 Controllers/BotController.cs create mode 100644 Dockerfile create mode 100644 DomvsChatBot.csproj create mode 100644 DomvsChatBot.sln create mode 100644 LocalData/LocalStorage.cs create mode 100644 MSGraph/TokenManager.cs create mode 100644 MSGraph/akjkpvjm.5o3~ create mode 100644 Program.cs create mode 100644 Properties/PublishProfiles/registry.redecarneir.us.pubxml create mode 100644 Properties/launchSettings.json create mode 100644 PushContainer.bat create mode 100644 TeamsApp/README.md create mode 100644 TeamsApp/TeamsApp.ttkproj create mode 100644 TeamsApp/appPackage.stg.zip create mode 100644 TeamsApp/appPackage/color.png create mode 100644 TeamsApp/appPackage/manifest.json create mode 100644 TeamsApp/appPackage/manifest.stg.json create mode 100644 TeamsApp/appPackage/outline.png create mode 100644 TeamsApp/appPackage/technical-support192.png create mode 100644 TeamsApp/appPackage/technical-support32.png create mode 100644 TeamsApp/appPackage/technical-support32n.png create mode 100644 TeamsApp/env/.env.dev create mode 100644 TeamsApp/env/.env.local create mode 100644 TeamsApp/env/.env.prod create mode 100644 TeamsApp/env/.env.stg create mode 100644 TeamsApp/infra/azure.bicep create mode 100644 TeamsApp/infra/azure.parameters.json create mode 100644 TeamsApp/infra/botRegistration/azurebot.bicep create mode 100644 TeamsApp/infra/botRegistration/readme.md create mode 100644 TeamsApp/launchSettings.json create mode 100644 TeamsApp/teamsapp.local.yml create mode 100644 TeamsApp/teamsapp.stg.yml create mode 100644 TeamsApp/teamsapp.yml create mode 100644 appsettings.TestTool.json create mode 100644 appsettings.json diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000..fe1152b --- /dev/null +++ b/.dockerignore @@ -0,0 +1,30 @@ +**/.classpath +**/.dockerignore +**/.env +**/.git +**/.gitignore +**/.project +**/.settings +**/.toolstarget +**/.vs +**/.vscode +**/*.*proj.user +**/*.dbmdl +**/*.jfm +**/azds.yaml +**/bin +**/charts +**/docker-compose* +**/Dockerfile* +**/node_modules +**/npm-debug.log +**/obj +**/secrets.dev.yaml +**/values.dev.yaml +LICENSE +README.md +!**/.gitignore +!.git/HEAD +!.git/config +!.git/packed-refs +!.git/refs/heads/** \ No newline at end of file diff --git a/AdapterWithErrorHandler.cs b/AdapterWithErrorHandler.cs new file mode 100644 index 0000000..a5429b9 --- /dev/null +++ b/AdapterWithErrorHandler.cs @@ -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 DomvsChatBot; + +public class AdapterWithErrorHandler : CloudAdapter +{ + public AdapterWithErrorHandler(BotFrameworkAuthentication auth, ILogger 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"); + } + }; + } +} \ No newline at end of file diff --git a/Bot/ChatIABot.cs b/Bot/ChatIABot.cs new file mode 100644 index 0000000..955131e --- /dev/null +++ b/Bot/ChatIABot.cs @@ -0,0 +1,171 @@ + using DomvsChatBot.Comm; +using DomvsChatBot.LocalData; +using DomvsChatBot.MSGraph; +using Microsoft.Bot.Builder; +using Microsoft.Bot.Builder.Teams; +using Microsoft.Bot.Connector.Authentication; +using Microsoft.Bot.Connector; +using Microsoft.Bot.Schema; +using Microsoft.Extensions.Configuration; +using System.Net.Http.Headers; +using System.Web; +using System.Text; + +namespace DomvsChatBot.Bot; + +public class ChatIABot : TeamsActivityHandler +{ + private readonly IConfigurationManager _configuration; + private readonly string _clientSecret; + private readonly string _clientId; + private readonly ApiService _apiService; + private readonly LocalStorage _localStorage; + private readonly TokenManager _tokenManager; + private readonly IHttpClientFactory _clientFactory; + + public ChatIABot(IConfigurationManager configuration, ApiService apiService, LocalStorage localStorage, TokenManager tokenManager, IHttpClientFactory clientFactory) + { + _configuration = configuration; + _apiService = apiService; + _localStorage = localStorage; + _tokenManager = tokenManager; + _clientFactory = clientFactory; + _clientSecret = _configuration.GetSection("AppClientSecret").Value; + _clientId = _configuration.GetSection("AppClientID").Value; + } + protected override async Task OnMessageActivityAsync(ITurnContext 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 = turnContext.Activity.From.AadObjectId.ToString(); + + var credentials = new MicrosoftAppCredentials(_clientId, _clientSecret); + var connector = new ConnectorClient(new Uri(turnContext.Activity.ServiceUrl), credentials); + var sessionId = turnContext.Activity.Conversation.Id; + var localId = turnContext.Activity.Conversation.TenantId; + + try + { + //var userInfo = await connector.Conversations.GetConversationMembersAsync(conversationId); + //var token = await TokenManager.ObterToken(userId); + //var replyText = await GetMessage(userId, turnContext.Activity.From.AadObjectId, turnContext.Activity.From.Name, messageText); + var token = await GetToken(userName, tenantId, userId); + await turnContext.SendActivityAsync(new Activity() { Type = ActivityTypes.Typing }); + + var taskResponse = _apiService.GetMessage(token, messageText, sessionId); + + var waitTime = 1000; + + while (!taskResponse.IsCompleted) + { + await Task.Delay(waitTime); + if (!taskResponse.IsCompleted) await turnContext.SendActivityAsync(new Activity() { Type = ActivityTypes.Typing }); + waitTime = GetTime(waitTime); + }; + + var replyText = await taskResponse; + replyText = SepararCodigo(replyText); + + await turnContext.SendActivityAsync(MessageFactory.Text(replyText), cancellationToken); + //await turnContext.SendActivityAsync(new Activity() { Type = ActivityTypes.Typing }); + + } + catch (Exception ex) + { + await turnContext.SendActivityAsync(MessageFactory.Text(ex.Message), cancellationToken); + } + } + + private string SepararCodigo(string texto) + { + if (texto.Contains("```")) + { + return texto; + } + return texto.Replace("\n", "
"); + } + + + private int GetTime(int waitTime) + { + return waitTime==1000 ? waitTime=2000 : waitTime == 2000 ? waitTime = 5000 : waitTime = 10000; + } + + protected override async Task OnMembersAddedAsync(IList membersAdded, ITurnContext turnContext, CancellationToken cancellationToken) + { + var welcomeText = "Olá! Eu sou a Domvs IA. A inteligência artificial 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(new Activity() { Type = ActivityTypes.Typing }); + + await turnContext.SendActivityAsync(MessageFactory.Text(welcomeText), cancellationToken); + //TODO: Verificar se o turnContext.Activity.Conversation.Id existe ou não bo BD do Bot (MongoDB localhost:27017) + + var userId = turnContext.Activity.From.Id; + var userName = turnContext.Activity.From.Name; + var localId = turnContext.Activity.Conversation.TenantId; + + await GetToken(userName, localId, userId); + + //var token = await TokenManager.ObterToken(userId); + //var replyText = await GetMessage(token, messageText); + //await turnContext.SendActivityAsync(MessageFactory.Text(replyText), cancellationToken); + + } + } + } + private async Task GetToken(string name, string company, string id) + { + if (_localStorage?.Token != null && _tokenManager.CheckTokenIsValid(_localStorage.Token)) + { + return _localStorage.Token; + } + + var secret = await _apiService.GetSecret(id, company, name); + var token = await _apiService.GetToken(id, name, secret); + + _localStorage.Secret = secret; + _localStorage.Token = token; + _localStorage.Name = name; + _localStorage.Company = company; + _localStorage.Id = id; + + return token; + } + + private async Task GetMessage(string jwt, string message) + { + var httpClient = _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; + } + + private async Task GetMessage(string id, string email, string name, string message) + { + var httpClient = _clientFactory.CreateClient(); + var content = ""; + using (var requestMessage = new HttpRequestMessage(HttpMethod.Get, $"http://localhost:5020/Chat?SessionId={HttpUtility.UrlEncode(id)}&Message={HttpUtility.UrlEncode(message)}&Email={HttpUtility.UrlEncode(email)}&Name={HttpUtility.UrlEncode(name)}")) + { + //requestMessage.Headers.Authorization = new AuthenticationHeaderValue("Bearer", jwt); + + var responseGet = await httpClient.SendAsync(requestMessage); + content = responseGet.Content.ReadAsStringAsync().Result; + } + + return content; + } +} + diff --git a/Comm/ApiService.cs b/Comm/ApiService.cs new file mode 100644 index 0000000..3de1bdc --- /dev/null +++ b/Comm/ApiService.cs @@ -0,0 +1,91 @@ +using Microsoft.AspNetCore.Components; +using Microsoft.AspNetCore.DataProtection; +using Newtonsoft.Json; +using Newtonsoft.Json.Linq; +using System.Net.Http.Headers; +using System.Text; +using System.Web; + +namespace DomvsChatBot.Comm +{ + public class ApiService + { + private readonly IHttpClientFactory _clientFactory; + private readonly IConfigurationManager _configurationManager; + private readonly string _baseUrl; + + public ApiService(IHttpClientFactory clientFactory, IConfigurationManager configurationManager) + { + _clientFactory = clientFactory; + _configurationManager = configurationManager; + _baseUrl = _configurationManager.GetSection("BaseUrlApi").Value; + } + + public async Task GetSecret(string id, string company, string name) + { + var httpClient = _clientFactory.CreateClient(); + var content = ""; + var secret = ""; + using (var requestMessage = new HttpRequestMessage(HttpMethod.Post, $"{_baseUrl}/login/newclient")) + { + //requestMessage.Headers.Authorization = new AuthenticationHeaderValue("Bearer", jwt); + var sendNew = new + { + localId = id, + companyTenant = company, + name = name + }; + requestMessage.Content = new StringContent(JsonConvert.SerializeObject(sendNew), Encoding.UTF8, "application/json"); + + var responseGet = await httpClient.SendAsync(requestMessage); + content = responseGet.Content.ReadAsStringAsync().Result; + + dynamic returned = JObject.Parse(content); + secret = returned.secret; + } + + return secret; + } + + public async Task GetToken(string clientId, string clientName, string clientSecret) + { + var httpClient = _clientFactory.CreateClient(); + var content = ""; + var token = ""; + using (var requestMessage = new HttpRequestMessage(HttpMethod.Post, $"{_baseUrl}/login/token")) + { + //requestMessage.Headers.Authorization = new AuthenticationHeaderValue("Bearer", jwt); + var sendNew = new + { + clientId = clientId, + clientName = clientName, + clientSecret = clientSecret + }; + requestMessage.Content = new StringContent(JsonConvert.SerializeObject(sendNew), Encoding.UTF8, "application/json"); + + var responseGet = await httpClient.SendAsync(requestMessage); + content = responseGet.Content.ReadAsStringAsync().Result; + + dynamic returned = JObject.Parse(content); + token = returned.token; + } + + return token; + } + + public async Task GetMessage(string token, string message, string sessionId) + { + var httpClient = _clientFactory.CreateClient(); + var content = ""; + using (var requestMessage = new HttpRequestMessage(HttpMethod.Get, $"{_baseUrl}/chat/response?SessionId={HttpUtility.UrlEncode(sessionId)}&Message={HttpUtility.UrlEncode(message)}")) + { + requestMessage.Headers.Authorization = new AuthenticationHeaderValue("Bearer", token); + + var responseGet = await httpClient.SendAsync(requestMessage); + content = responseGet.Content.ReadAsStringAsync().Result; + } + + return content; + } + } +} diff --git a/Config.cs b/Config.cs new file mode 100644 index 0000000..0da06de --- /dev/null +++ b/Config.cs @@ -0,0 +1,8 @@ +namespace DomvsChatBot +{ + public class ConfigOptions + { + public string BOT_ID { get; set; } + public string BOT_PASSWORD { get; set; } + } +} diff --git a/Controllers/BotController.cs b/Controllers/BotController.cs new file mode 100644 index 0000000..f561ba5 --- /dev/null +++ b/Controllers/BotController.cs @@ -0,0 +1,37 @@ +using Microsoft.AspNetCore.Mvc; +using Microsoft.Bot.Builder; +using Microsoft.Bot.Builder.Integration.AspNet.Core; + +namespace DomvsChatBot.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); + } + + [HttpGet] + [Route("health")] + public async Task Health() + { + return Ok("It´s ready!"); + } +} \ No newline at end of file diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..ddbfde4 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,29 @@ +# See https://aka.ms/customizecontainer to learn how to customize your debug container and how Visual Studio uses this Dockerfile to build your images for faster debugging. + +# This stage is used when running from VS in fast mode (Default for Debug configuration) +FROM mcr.microsoft.com/dotnet/aspnet:8.0 AS base +USER app +WORKDIR /app +EXPOSE 8080 + + +# This stage is used to build the service project +FROM mcr.microsoft.com/dotnet/sdk:8.0 AS build +ARG BUILD_CONFIGURATION=Release +WORKDIR /src +COPY ["DomvsChatBot.csproj", "."] +RUN dotnet restore "./DomvsChatBot.csproj" +COPY . . +WORKDIR "/src/." +RUN dotnet build "./DomvsChatBot.csproj" -c $BUILD_CONFIGURATION -o /app/build + +# This stage is used to publish the service project to be copied to the final stage +FROM build AS publish +ARG BUILD_CONFIGURATION=Release +RUN dotnet publish "./DomvsChatBot.csproj" -c $BUILD_CONFIGURATION -o /app/publish /p:UseAppHost=false + +# This stage is used in production or when running from VS in regular mode (Default when not using the Debug configuration) +FROM base AS final +WORKDIR /app +COPY --from=publish /app/publish . +ENTRYPOINT ["dotnet", "DomvsChatBot.dll"] \ No newline at end of file diff --git a/DomvsChatBot.csproj b/DomvsChatBot.csproj new file mode 100644 index 0000000..cb4da43 --- /dev/null +++ b/DomvsChatBot.csproj @@ -0,0 +1,17 @@ + + + + net8.0 + enable + Linux + . + + + + + + + + + + diff --git a/DomvsChatBot.sln b/DomvsChatBot.sln new file mode 100644 index 0000000..320d9f4 --- /dev/null +++ b/DomvsChatBot.sln @@ -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}") = "DomvsChatBot", "DomvsChatBot.csproj", "{9F6D5611-03E4-4272-AAAC-4F1E9447A1E9}" +EndProject +Project("{A9E3F50B-275E-4AF7-ADCE-8BE12D41E305}") = "TeamsApp", "TeamsApp\TeamsApp.ttkproj", "{EA5FD4C0-E5A1-4E35-A713-350E3249BB83}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {9F6D5611-03E4-4272-AAAC-4F1E9447A1E9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {9F6D5611-03E4-4272-AAAC-4F1E9447A1E9}.Debug|Any CPU.Build.0 = Debug|Any CPU + {9F6D5611-03E4-4272-AAAC-4F1E9447A1E9}.Release|Any CPU.ActiveCfg = Release|Any CPU + {9F6D5611-03E4-4272-AAAC-4F1E9447A1E9}.Release|Any CPU.Build.0 = Release|Any CPU + {EA5FD4C0-E5A1-4E35-A713-350E3249BB83}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {EA5FD4C0-E5A1-4E35-A713-350E3249BB83}.Debug|Any CPU.Build.0 = Debug|Any CPU + {EA5FD4C0-E5A1-4E35-A713-350E3249BB83}.Release|Any CPU.ActiveCfg = Release|Any CPU + {EA5FD4C0-E5A1-4E35-A713-350E3249BB83}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {B82DBB78-4321-4286-85F1-497096661AAA} + EndGlobalSection +EndGlobal diff --git a/LocalData/LocalStorage.cs b/LocalData/LocalStorage.cs new file mode 100644 index 0000000..803c49e --- /dev/null +++ b/LocalData/LocalStorage.cs @@ -0,0 +1,11 @@ +namespace DomvsChatBot.LocalData +{ + public class LocalStorage + { + public string Token { get; set; } + public string Secret { get; set; } + public string Name { get; set; } + public string Company { get; set; } + public string Id { get; set; } + } +} diff --git a/MSGraph/TokenManager.cs b/MSGraph/TokenManager.cs new file mode 100644 index 0000000..31a83b3 --- /dev/null +++ b/MSGraph/TokenManager.cs @@ -0,0 +1,116 @@ +using Microsoft.Identity.Client; +using System.IdentityModel.Tokens.Jwt; + +namespace DomvsChatBot.MSGraph +{ + public class TokenManager + { + private readonly IConfiguration _configuration; + private readonly string _clienteSecret; + private readonly string _tenantId; + private readonly string _clientId; + + public TokenManager(IConfigurationManager configuration) + { + _configuration = configuration; + _clienteSecret = _configuration.GetSection("AppClientSecret").Value; + _tenantId = _configuration.GetSection("AppTenantId").Value; + _clientId = _configuration.GetSection("AppClientID").Value; + } + + //public async Task ObterEmail(string aadObjectId) + //{ + // // The Microsoft Entra ID tenant ID or a verified domain (e.g. contoso.onmicrosoft.com) + // var tenantId = _tenantId; + + // // The client ID of the app registered in Microsoft Entra ID + // var clientId = _clientId; + + // // *Never* include client secrets in source code! + // var clientSecret = _clienteSecret; // Or some other secure place. + + // // Create an instance of a TokenCredential. Since we're using the Client Credentials + // // flow with a client secret, we use ClientSecretCredential. + // var clientSecretCredential = new ClientSecretCredential(tenantId, clientId, clientSecret); + + // // The app registration should be configured to require access to permissions + // // sufficient for the Microsoft Graph API calls the app will be making, and + // // those permissions should be granted by a tenant administrator. + // var scopes = new[] { "https://graph.microsoft.com/.default" }; + + // // Build the Microsoft Graph client + // GraphServiceClient graphServiceClient = new GraphServiceClient(clientSecretCredential, scopes); + + // // Make a Microsoft Graph API request + // var users = await graphServiceClient.Users.GetAsync(); + + // return users.Value.FirstOrDefault(x => x.Id == aadObjectId).Mail; + //} + //public async Task ObterToken(string userEmail) + //{ + // try + // { + // var app = PublicClientApplicationBuilder + // .Create(_clientId) + // .WithAuthority(AzureCloudInstance.AzurePublic, _tenantId) + // .WithDefaultRedirectUri() + // .Build(); + + // string[] scopes = new string[] { + // //"https://graph.microsoft.com/.default", + // "User.Read", // Exemplo de escopo básico + // "email", + // "profile", + // "openid" + // }; + + // var accounts = await app.GetAccountsAsync(); + // string accessToken = ""; + // if (accounts.Any()) + // { + // var result = await app.AcquireTokenSilent(scopes, accounts.FirstOrDefault()) + // .ExecuteAsync(); + // accessToken = result.AccessToken; + // } + // else + // { + // var interactiveResult = await app + // .AcquireTokenInteractive(scopes) + // .ExecuteAsync(); + + // accessToken = interactiveResult.AccessToken; + // var email = interactiveResult.Account.Username; + // } + + // return accessToken; + // } + // catch (Exception ex) + // { + // // Tratamento de erro + // Console.WriteLine($"Erro ao obter token: {ex.Message}"); + // return null; + // } + //} + + public long GetTokenExpirationTime(string token) + { + var handler = new JwtSecurityTokenHandler(); + var jwtSecurityToken = handler.ReadJwtToken(token); + var tokenExp = jwtSecurityToken.Claims.First(claim => claim.Type.Equals("exp")).Value; + var ticks = long.Parse(tokenExp); + return ticks; + } + + public bool CheckTokenIsValid(string token) + { + var tokenTicks = GetTokenExpirationTime(token); + var tokenDate = DateTimeOffset.FromUnixTimeSeconds(tokenTicks).UtcDateTime; + + var now = DateTime.Now.ToUniversalTime(); + + var valid = tokenDate >= now; + + return valid; + } + } +} diff --git a/MSGraph/akjkpvjm.5o3~ b/MSGraph/akjkpvjm.5o3~ new file mode 100644 index 0000000..f5aa6aa --- /dev/null +++ b/MSGraph/akjkpvjm.5o3~ @@ -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 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; + } + } + } + } +} diff --git a/Program.cs b/Program.cs new file mode 100644 index 0000000..4b35f93 --- /dev/null +++ b/Program.cs @@ -0,0 +1,61 @@ +using DomvsChatBot; +using DomvsChatBot.Bot; +using DomvsChatBot.Comm; +using DomvsChatBot.LocalData; +using DomvsChatBot.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(); +builder.Configuration["MicrosoftAppType"] = "MultiTenant"; +builder.Configuration["MicrosoftAppId"] = config.BOT_ID; +builder.Configuration["MicrosoftAppPassword"] = config.BOT_PASSWORD; +builder.Services.AddSingleton(); + +builder.Services.AddSingleton(builder.Configuration); + +// Create the Bot Framework Adapter with error handling enabled. +builder.Services.AddSingleton(); + + +//TODO: Remover quando adicionar LiteDB +builder.Services.AddSingleton(); + +builder.Services.AddScoped(); +builder.Services.AddScoped(); + +// Create the Bot Framework Adapter with error handling enabled. +builder.Services.AddSingleton(); + +// Create the bot as a transient. In this case the ASP Controller is expecting an IBot. +builder.Services.AddTransient(); + +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(); \ No newline at end of file diff --git a/Properties/PublishProfiles/registry.redecarneir.us.pubxml b/Properties/PublishProfiles/registry.redecarneir.us.pubxml new file mode 100644 index 0000000..5d933b8 --- /dev/null +++ b/Properties/PublishProfiles/registry.redecarneir.us.pubxml @@ -0,0 +1,18 @@ + + + + + Container + NetSdk + registry.redecarneir.us + latest + ContainerRegistry + Release + Any CPU + linux-x64 + 9f6d5611-03e4-4272-aaac-4f1e9447a1e9 + <_TargetId>NetSdkCustomContainerRegistry + + \ No newline at end of file diff --git a/Properties/launchSettings.json b/Properties/launchSettings.json new file mode 100644 index 0000000..08a037e --- /dev/null +++ b/Properties/launchSettings.json @@ -0,0 +1,32 @@ +{ + "profiles": { + "Start Project": { + "commandName": "Project", + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + }, + "dotnetRunMessages": true, + "applicationUrl": "http://localhost:5130", + "hotReloadProfile": "aspnetcore" + }, + "Teams App Test Tool": { + "commandName": "Project", + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "TestTool", + "TEAMSFX_NOTIFICATION_STORE_FILENAME": ".notification.testtoolstore.json" + }, + "dotnetRunMessages": true, + "applicationUrl": "http://localhost:5130", + "hotReloadProfile": "aspnetcore" + }, + "Container (Dockerfile)": { + "commandName": "Docker", + "launchUrl": "{Scheme}://{ServiceHost}:{ServicePort}", + "environmentVariables": { + "ASPNETCORE_HTTP_PORTS": "8080" + }, + "publishAllPorts": true, + "useSSL": false + } + } +} \ No newline at end of file diff --git a/PushContainer.bat b/PushContainer.bat new file mode 100644 index 0000000..db6a68e --- /dev/null +++ b/PushContainer.bat @@ -0,0 +1,4 @@ +cd C:\vscode\OpenRHCall +docker build -t open-rh-call . +docker tag domvs-chat-bot registry.redecarneir.us/domvs-chat-bot:latest +docker push registry.redecarneir.us/domvs-chat-bot:latest diff --git a/TeamsApp/README.md b/TeamsApp/README.md new file mode 100644 index 0000000..f680e12 --- /dev/null +++ b/TeamsApp/README.md @@ -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 +
![image](https://raw.githubusercontent.com/OfficeDev/TeamsFx/dev/docs/images/visualstudio/debug/create-devtunnel-button.png) +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 +
![image](https://raw.githubusercontent.com/OfficeDev/TeamsFx/dev/docs/images/visualstudio/debug/debug-button.png) +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 diff --git a/TeamsApp/TeamsApp.ttkproj b/TeamsApp/TeamsApp.ttkproj new file mode 100644 index 0000000..1833645 --- /dev/null +++ b/TeamsApp/TeamsApp.ttkproj @@ -0,0 +1,12 @@ + + + + ea5fd4c0-e5a1-4e35-a713-350e3249bb83 + + + + + + + + \ No newline at end of file diff --git a/TeamsApp/appPackage.stg.zip b/TeamsApp/appPackage.stg.zip new file mode 100644 index 0000000000000000000000000000000000000000..1a71360fae7e54a084277097f3e1b296b2b0c659 GIT binary patch literal 11653 zcmZ{q1#I0=x210yrsf73W@c)blZMkUGcz+Yr(vcWriPiBnVFfHIn#een)gO}V{3b9 z+g_5r&py_%^vOwqL!bcwFff2BpA7W~qPibB-vEF{NB{s4003C)+nAdeJ37%@INI7o zDM{O|iz0NqsRAux;`SdZcVjYkNK25+{kl)cj{ULa+Yn4bdhP0Mu%DOifuu_XU3y4TocvU3WM|eQd%61grsPpon;7lb3^_9r2RXc zF(hifEp&4%SWxnrIukd8Zp?NY8f{}NaZjD8CS7Qj=Ik>xr16c!Pvz*72No}l@j(uD zs`<>N1xW32hq~q*FDBp3!;~oua{hrIXy9EuQjH@|#S zgZ?g70f1}&xR@qm3Gr&js(MLL?PIqQpkqSpe-nd$WQ%@T)2}f3bK1@c%075#FTE2{ zp15nZkmj?sV`5j@YwyV9Xz73^!NZ%qa`g*{5c5>3!*O(y9Y_&;rQa}jiG90MbK&lK zjkw6!%v0v-t^TBs(_~8>Jc?=}5ZflX+%Xc$!mO6v3O1Y{L z?6VjcIpX3SN)UuUq7Eaz4BzNo;Qif=pY?o6*OJz6f+1PKrekO5C%TGuzP$#Q`@gLW z5R6w>hQ|v04F&*+{R{Yit!(S;WMyt+OmAmn3MK~D{24AMBZdfv4fpR7qJ+4x!apVa zPryL^J34xJ-2W3;J8^Z#e|FUW1Q;Ma6Z79mFh>P3AwcCM?#aId!c6!c#Ya>{`f^Gl`Spv} z=tF?G3Ec0H);@i?Ap68O?3>Qk=${H;NtJi^M8bj~d3iy` zWgN;ldFc9#02q{duQgG1Ts*(w^jVh<>o>YNt<_d|3qR~`488im%hY_M-O01@Fuc(j zIB*-^LEc*?Kl8q%u6;Nx*tk;zl;Mki?+K6)krA#G(hK;nqKlOqtMle=K=4xn0HXim zKeci)HZ-&OH?6Jc9G&g#Y#p4KIGO)50^Y77a<~XNcM9w1u5_Du0~-w-Xs)iy0}ah} z;x$6{lnUz=&2*P?PWG;pi;$l$pYA`e9>2Gcrj0O3l!v5$V}s)SH%i?q3W*E4nXhCFrz z1o*j2OQ@XwsXB3|_aL0v9o6({a~MRDXf+~*qGamA$HtBq5baU0Y|t+mQeGN5ObN^919?yu&G3@lSIRlVbwecw7K z)OW>BwK*X`IX-Sqj1qg^p_HF2L-W=i_2}=8h=FnHD=0D~++Be_&YFATbtbcRYW!YNfTdC;-_;)G>cHjB=c90|VLJZut#VY($EDMSc^> zqiT-6)?>(KyHjE($0e@1p7SmPJUB|gjGu%;AKJKMNy#UtDERLdxF3IiN@0D3QUMXy%3^N{~ zCJI{e-||X=BIq63g_AGyLhOkP(wqxj2J3E{z+1hJCDcyZTEIa8UF&X!e*~A0SC#yxLH7-L<=1 zeLXP##1WkH+ksoCx+r=%l!t@AFI^AaT(rgpdRXD|gv2uIZ5>R&6!}g!ZVFKh zbC(q9wGrMa5FX$BjZ8$o@0%7okuy0vF1K2!?=PqR!O98dCh%!b~K60Xni^e2z#!kKKs2*u7Kdl2m0Z3?LCry|J@ z)QydLMPqt`{%RonJCAn0gz0FOCf-*%zLZjp*+ZIzWj^nxcF8X2J4%n0a33Y^)Xjit zUS@QupDd8VW51(@wc_MZczs#6&1<3^DjUsuhxBxZT}zL4sSJ?9;BFt#|A+K6gSL%d zQSE$2b&j7KqAbENLOl$!P_x+noBD&b_1M@J0bz~so8^MFQv&q?Z8f?}@WyG2p9DT5 z$3nWGr+6rRUQRaFDz*N@M*So2fd0f(Wx(!^L>7m&|dG(Cvj9 zkk)lMv(nA}b{Ho5?iedOtKe?Rp!t?`OtTCYt#8BKVT@=&0}QFsMoiw4)wj|}>~1^h zlznl<7vwVbhv@FI7q$qH#3$;KAr3tbnjmZ&HMKaH$-y3QV#d?u5rk+P$H_5aZ`OUE zZ!bu-EGlw`1~DxLu`NMUg=z&r87U+K-YBrF&z&f6fAV9aImkiy|<HPkCT3iJ^YrA%Rw2CLj=ioSk7$(~tV}>c2poZMDceCR zlT#G_X?NreuyBH=?bcgoG2lrA(J>C;l5rl7rqx;q#X2aU;IpA2+x*; z6b6NY{$N_SP--G~9sedUDaNLWc2M$2hoIH3c0i>+hkQhcWUG$#n%SY{Ac*%gh4I5A zgEs}iFQ0og!IV_yCybz+5AR%&)$k{L-Y{g0D@IlRa_Df&+zVYAB(S{@lAsoAd^SAu zFTalS?Y?#uR7wif}{FF{1Kkk6kmj(I`PU+^D z75Kq~&RwStqO@Xmtc8tK1<^7M7|ZCB2%gAdSD|_hvh-m_1Rbzw8jZ?j4%%2)8KkvR zD;J|#2YR2&=0NjsJVCRcW}9KZ=?fVUl(ri_9?pPb{%>@>Jlh1+;?{|=vkkQo^;0yN z*L`h=Iq0f4x%fdXJf$o9`0NZAQfOC1WUg25857HjavdkD+wBkM7cB?PwdCgN{*IpO z+Hha>FOGKo-S6)^1*d!IQtRI6zH)G*mpkdVknHZG z?8;oh587QH)I)}rTAa9S(<#%*(Uc%f%EJE$DgCru{3PKQ4UtL#vqNVX$UZZ?+) z3Y7#!+$u-Yr!@004|aA6zoRqOtwI4x-vdw-jP+XJMpi-{WIaimulyLQT4!KAcgj9k zWXUn9%5*9_CpTXLr_qt#%dQkOj2=XhaNO=Vd&*7^sk&%tpd9=n!F|LUG)lu4OoND* ztv2u>A5U_3ZM(`rhb6k~byuj;{ANC8vi8`)X5s255hwnu z?^$-q2Q^%ZA+|v>Fn-u*(|;kOG)G>$+dZo}SkfUahU7V8uDa0L@^36rfRW^Je(}Q8 zKB6X@rYj%n8v&iO!B6G&P!oI~Vq#LT21F4~&~cv{YZHP1tWKG%x7Yogx6b5Iq;vG$ zlT~TcoA*Q*p8LqrE;$Fm$=qy;4`@=9=-p_1hGaJlivqR1R(#6Zt*EQcNu!^Y4=o>U z9k|p%@LZXrFzLY2{%GzB6tt#v$~0*J9pi(O1m(=fo1??Trs*VaG*o65vtE|wQW1rh zXqTqYBu{RTwiADS9nxQuroFHzTvzzekAA1%f---%V8)*XTH@Lxv^ur?=$9*OSx&88XH`H#eAtQps0?u>Tb2(d zoXa6fO5~2i&G6AT!$7gX+UcoYTdQ+1FuEBA-mTW^cTx+MpLHbJAdRV@ZGQDwpiU1s z1zs8aT#tw|X3F5-kjR{FRLkp+~R1 z884E4oFR*7fpFxj{V+eBt)AxJO;0fUTcin0ere$F<_6CP@8U=f@euM{OJluEIG|A) z;=>4HR_`7HTNo9GLrh6bf0v*pTd@mX?LioDBZ1@Y1WypGqB4j-0MMx=Pj`WDvGjrt zDS=#Q+Gwm`CD$cq;IF{$Nq2 z1{k^U9iP7kVm?2iSvpSp001mcde-ymOb&U3q|9pSjr=Ft*mLkiunx7 z@NTINaB+Is_6XP*E6DB`)`#M|TBoe-398V}*jYmMhDM9Byj1skLzrY`RM?+E9ys+7 zY;_$FLZt|r%0Dxg)VQx84_$p*)#vp_B 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 literal 0 HcmV?d00001 diff --git a/TeamsApp/appPackage/manifest.json b/TeamsApp/appPackage/manifest.json new file mode 100644 index 0000000..e93ffd3 --- /dev/null +++ b/TeamsApp/appPackage/manifest.json @@ -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.1", + "id": "${{TEAMS_APP_ID}}", + "developer": { + "name": "Domvs iT - Ricardo Carneiro", + "websiteUrl": "https://www.domvsit.com", + "privacyUrl": "https://www.domvsit.com/privacy", + "termsOfUseUrl": "https://www.domvsit.com/termofuse" + }, + "icons": { + "color": "technical-support192.png", + "outline": "outline.png" + }, + "name": { + "short": "Domvs IA", + "full": "Chat com IA e robô de solicitações" + }, + "description": { + "short": "Chat com IA e robô de solicitações", + "full": "Esta aplicação permite conversar e ter assitencia em liguamgem natural. Além disso, você pode fazer perguntas sobre o portifólio de serviços Domvs It e até abrir solicitações ao RH" + }, + "accentColor": "#FFFFFF", + "bots": [ + { + "botId": "${{BOT_ID}}", + "scopes": [ + "personal", + "team", + "groupChat" + ], + "supportsFiles": false, + "isNotificationOnly": false + } + ], + "composeExtensions": [ + ], + "configurableTabs": [], + "staticTabs": [], + "permissions": [ + "identity", + "messageTeamMembers" + ], + "validDomains": [] +} \ No newline at end of file diff --git a/TeamsApp/appPackage/manifest.stg.json b/TeamsApp/appPackage/manifest.stg.json new file mode 100644 index 0000000..a1ac078 --- /dev/null +++ b/TeamsApp/appPackage/manifest.stg.json @@ -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": "Domvs iT - Ricardo Carneiro", + "websiteUrl": "https://www.domvsit.com", + "privacyUrl": "https://www.domvsit.com/privacy", + "termsOfUseUrl": "https://www.domvsit.com/termofuse" + }, + "icons": { + "color": "technical-support192.png", + "outline": "outline.png" + }, + "name": { + "short": "Domvs IA", + "full": "Chat com IA e robô de solicitações" + }, + "description": { + "short": "Chat com IA e robô de solicitações", + "full": "Esta aplicação permite conversar e ter assitencia em liguamgem natural. Além disso, você pode fazer perguntas sobre o portifólio de serviços Domvs It e até abrir solicitações ao RH" + }, + "accentColor": "#FFFFFF", + "bots": [ + { + "botId": "${{BOT_ID}}", + "scopes": [ + "personal", + "team", + "groupChat" + ], + "supportsFiles": false, + "isNotificationOnly": false + } + ], + "composeExtensions": [ + ], + "configurableTabs": [], + "staticTabs": [], + "permissions": [ + "identity", + "messageTeamMembers" + ], + "validDomains": [] +} \ No newline at end of file diff --git a/TeamsApp/appPackage/outline.png b/TeamsApp/appPackage/outline.png new file mode 100644 index 0000000000000000000000000000000000000000..245fa194db6e08d30511fdbf26aec3c6e2c3c3c8 GIT binary patch literal 327 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnE1|*BCs=fdz&H|6fVg?3oVGw3ym^DWND9BhG z9;9t*EM+Qm zy2D^Lfp=fIpwQyAe|y)?x-or<+J~Ptr@l6Mq%piHi4jOQ$W@+cm^^pek{T^R1~YT6 z#nC6He`LE*@cXCq-bL3hdgYxF$=uQYd!tVN6U(~0f70B<4PQ*lTGqqND0QE8cCxF; zrA^=emkHKQ+WI8@(#FJB4wBw$4jk;^oXcu!J2!Q;MX2;5u|xv~4xueIx7{LTWE)P* zx>U9|_qXolm|MHJvl^rhh$n1mem7%r%A<3y&veM1y2!zda7l7b Ve3c}0;w{jh44$rjF6*2UngINOfUy7o literal 0 HcmV?d00001 diff --git a/TeamsApp/appPackage/technical-support192.png b/TeamsApp/appPackage/technical-support192.png new file mode 100644 index 0000000000000000000000000000000000000000..a4a00e0c8791a059bb99af88d51fbff92627d60f GIT binary patch literal 10310 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 literal 0 HcmV?d00001 diff --git a/TeamsApp/appPackage/technical-support32n.png b/TeamsApp/appPackage/technical-support32n.png new file mode 100644 index 0000000000000000000000000000000000000000..899922d426358eff495e7969411daeef43a555bf GIT binary patch literal 1703 zcmV;Y23YxtP)Px#1ZP1_K>z@;j|==^1poj532;bRa{vGi!2kdb!2!6DYwZ9420TebK~z{rtygJm z6;&AhX6C*2^|ggU7arKMga*M#g#tne0tTuH7&M^#5~HBeL<|r>h@!>?BPxbejll@U zKPm)V5HL`IfEq-ws0c+;5!%|;vUPc#_H8qsb7x*@=>nCW*2q`ZMULB0dQUe@v75PGw=c&qfWPHKr9agW35&SC)R6jTcKS6 zaJUQNkkgarVf?z=z9}H?a}aBto=ipD@7;EX-TaCxxA#_Z!i}}v>9yuiXe|I$7C=k~ zL*R?l^)eWfv8TJa6xz}2^fUJibgH3-zwG+WU zhuqQ~U7MZsf$svwU@Yi}7FT-RoE=U9p^j#S% zHngP=d6&e88l3g0x^xC)X5@QNJ%iTO)ytP(?~%1{eJESE z@0JS}E-AgoV<@ss9mi-xTlzRQ9u?jQerrmjf$# zu0;yx=E}>f7QrSCUVl%h@kck}+mu zOot3sHp#;I`SR@2g_4+PNJWkJhpC(T4w;l{<;1Wf>LPk6qCB7@=N$A$)rNJc3UNiW zoM5v)#e-jezPwU4Zz~aBHjT*Y84 z#$;^fU@qolZe~BIx!H-iRt8EE*B`fn{yqBU_VAN+%H-52?e5Mq=+$bvPdFow%WL{4IRg5qfeNm zeCVrUbPZdbg08`mVN%~LcJ)8%8Ddpc;xtD@nz1CcjSks{PL09FuC7u(%D3amYX>#` z-GVXvUWvZHQS|)LVjVdy5{`+n>@nPnycmICP-5#olGq2E#4afjtK@|85gmnI2klC{ zb}e`ntH&44y3}3~YwKQY-yjkvh*eP``mG}s*`|(T$_BQ|hqKXo2|BnYhsFXhe-2b7 zu!#Gl_s4S($IWbxii!0!{fS~mEHS-aY5J^K>K|RA$ToFqj5f4|4}H_qohPM=3AR|8 zgsxT*)^e9yL($+po=Z)csZ}3*qVDA2KxBR>9F-lr_Q{@uCAht?lWEWv@k-SezY1!3 zCEq(OU*^o7flJ6Eu=(WvI*<=o|gb{)&R6#Mo|J`e#bZGsmo45NPi3qv9y5 ztQ`$e1WrUD{8IL?1i_7Oa~J*$K9ifBb>hI0V}+KjVUx(o;e#sg7&`d=SeFIFfkK8s z_?=$oK!NRxvyt4X*F@sKl@7og;2wxQ;3<5L$IP5OHgeqpdJ`z%ZixM0?-by_^AT=w zKDS4JJh1pa*~Yj)>X~(G9{&V0!)2hF;6vv=kgwv?C?Kyl3Rnffe_mQ)nh}{hahN={ za2_5eT34I*TRg{RvB7)bW>DkGtHAd)66I&wF30Wwr7dw+%K>m1sBp70K>v9lmq0xZ xaJG#=lIQHFMJslM!(p9|k+#4u$5k4K$bS}3k$(EIBYyw@002ovPDHLkV1gVaD+2%k literal 0 HcmV?d00001 diff --git a/TeamsApp/env/.env.dev b/TeamsApp/env/.env.dev new file mode 100644 index 0000000..10d9476 --- /dev/null +++ b/TeamsApp/env/.env.dev @@ -0,0 +1,16 @@ +# 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= +SECRET_BOT_PASSWORD= \ No newline at end of file diff --git a/TeamsApp/env/.env.local b/TeamsApp/env/.env.local new file mode 100644 index 0000000..730c0f0 --- /dev/null +++ b/TeamsApp/env/.env.local @@ -0,0 +1,19 @@ +# 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=1457d032-b35b-4553-b5fc-3da43ceba3f9 +TEAMS_APP_ID=04dff49e-3e13-4f42-a79e-6bd8035bcf1f +TEAMS_APP_TENANT_ID=20190830-5fd4-4a72-b8fd-1c1cb35b25bc +BOT_OBJECT_ID=dee85fe4-1f93-4f33-98eb-2ce668621232 +TEAMS_APP_TENANT_ID=20190830-5fd4-4a72-b8fd-1c1cb35b25bc +BOT_OBJECT_ID=dee85fe4-1f93-4f33-98eb-2ce668621232 + +#BOT_ENDPOINT=https://vrzg2z27-5130.brs.devtunnels.ms +BOT_ENDPOINT=https://api.lhost.dynu.net +BOT_DOMAIN=vrzg2z27-5130.brs.devtunnels.ms + +TEAMSFX_M365_USER_NAME=ricardo.carneiro@domvsit.com.br \ No newline at end of file diff --git a/TeamsApp/env/.env.prod b/TeamsApp/env/.env.prod new file mode 100644 index 0000000..5566649 --- /dev/null +++ b/TeamsApp/env/.env.prod @@ -0,0 +1,18 @@ +# 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=stg +APP_NAME_SUFFIX=stg + +# Generated during provision, you can also add your own variables. +BOT_ID=1457d032-b35b-4553-b5fc-3da43ceba3f9 +TEAMS_APP_ID=d7b58e81-c48e-436f-964c-0ab57b52ba95 +TEAMS_APP_TENANT_ID=20190830-5fd4-4a72-b8fd-1c1cb35b25bc +BOT_OBJECT_ID=dee85fe4-1f93-4f33-98eb-2ce668621232 +TEAMS_APP_TENANT_ID=20190830-5fd4-4a72-b8fd-1c1cb35b25bc +BOT_OBJECT_ID=dee85fe4-1f93-4f33-98eb-2ce668621232 + +TEAMSFX_M365_USER_NAME=ricardo.carneiro@domvsit.com.br + +BOT_ENDPOINT=https://vrzg2z27-5130.brs.devtunnels.ms +BOT_DOMAIN=vrzg2z27-5130.brs.devtunnels.ms \ No newline at end of file diff --git a/TeamsApp/env/.env.stg b/TeamsApp/env/.env.stg new file mode 100644 index 0000000..4137157 --- /dev/null +++ b/TeamsApp/env/.env.stg @@ -0,0 +1,19 @@ +# 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=stg +APP_NAME_SUFFIX=stg + +# Generated during provision, you can also add your own variables. +BOT_ID=1457d032-b35b-4553-b5fc-3da43ceba3f9 +TEAMS_APP_ID=d7b58e81-c48e-436f-964c-0ab57b52ba95 +TEAMS_APP_TENANT_ID=20190830-5fd4-4a72-b8fd-1c1cb35b25bc +BOT_OBJECT_ID=dee85fe4-1f93-4f33-98eb-2ce668621232 +TEAMS_APP_TENANT_ID=20190830-5fd4-4a72-b8fd-1c1cb35b25bc +BOT_OBJECT_ID=dee85fe4-1f93-4f33-98eb-2ce668621232 + +TEAMSFX_M365_USER_NAME=ricardo.carneiro@domvsit.com.br + +#BOT_ENDPOINT=https://vrzg2z27-5130.brs.devtunnels.ms +BOT_ENDPOINT=https://api.lhost.dynu.net +BOT_DOMAIN=vrzg2z27-5130.brs.devtunnels.ms \ No newline at end of file diff --git a/TeamsApp/infra/azure.bicep b/TeamsApp/infra/azure.bicep new file mode 100644 index 0000000..96ed8d8 --- /dev/null +++ b/TeamsApp/infra/azure.bicep @@ -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 diff --git a/TeamsApp/infra/azure.parameters.json b/TeamsApp/infra/azure.parameters.json new file mode 100644 index 0000000..edae770 --- /dev/null +++ b/TeamsApp/infra/azure.parameters.json @@ -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": "Domvs IA" + } + } + } \ No newline at end of file diff --git a/TeamsApp/infra/botRegistration/azurebot.bicep b/TeamsApp/infra/botRegistration/azurebot.bicep new file mode 100644 index 0000000..ab67c7a --- /dev/null +++ b/TeamsApp/infra/botRegistration/azurebot.bicep @@ -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' + } +} diff --git a/TeamsApp/infra/botRegistration/readme.md b/TeamsApp/infra/botRegistration/readme.md new file mode 100644 index 0000000..d541624 --- /dev/null +++ b/TeamsApp/infra/botRegistration/readme.md @@ -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. \ No newline at end of file diff --git a/TeamsApp/launchSettings.json b/TeamsApp/launchSettings.json new file mode 100644 index 0000000..600bcab --- /dev/null +++ b/TeamsApp/launchSettings.json @@ -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", + }, + } +} \ No newline at end of file diff --git a/TeamsApp/teamsapp.local.yml b/TeamsApp/teamsapp.local.yml new file mode 100644 index 0000000..b132cb6 --- /dev/null +++ b/TeamsApp/teamsapp.local.yml @@ -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: DomvsChatBot${{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: DomvsChatBot${{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: DomvsChatBot + 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 diff --git a/TeamsApp/teamsapp.stg.yml b/TeamsApp/teamsapp.stg.yml new file mode 100644 index 0000000..b132cb6 --- /dev/null +++ b/TeamsApp/teamsapp.stg.yml @@ -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: DomvsChatBot${{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: DomvsChatBot${{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: DomvsChatBot + 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 diff --git a/TeamsApp/teamsapp.yml b/TeamsApp/teamsapp.yml new file mode 100644 index 0000000..1a4199b --- /dev/null +++ b/TeamsApp/teamsapp.yml @@ -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: DomvsIA-${{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: DomvsIA-${{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 DomvsChatBot.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: 8c10d301-cb55-4445-b100-971f13405827 diff --git a/appsettings.TestTool.json b/appsettings.TestTool.json new file mode 100644 index 0000000..1a3d21d --- /dev/null +++ b/appsettings.TestTool.json @@ -0,0 +1,12 @@ +{ + "Logging": { + "LogLevel": { + "Default": "Information", + "Microsoft": "Warning", + "Microsoft.Hosting.Lifetime": "Information" + } + }, + "AllowedHosts": "*", + "BOT_ID": "", + "BOT_PASSWORD": "" +} \ No newline at end of file diff --git a/appsettings.json b/appsettings.json new file mode 100644 index 0000000..b72702f --- /dev/null +++ b/appsettings.json @@ -0,0 +1,17 @@ +{ + "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", + "BaseUrlApi": "https://api.lhost.dynu.net" +}