<?xml version="1.0" encoding="utf-8"?>
<AlvaoApplication xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" ModelVersion="1">
  <Applications>
    <Application id="42">
      <Name>Ticket Create Task In To Do</Name>
      <Description>To the Request page, adds the “Create task” command that creates a new task in MS To Do.</Description>
      <UniqueId>e8c8d2fd-a909-4f10-a922-e630f34f9ea9</UniqueId>
      <Version>2</Version>
      <AdvancedSettings />
      <Scripts>
        <Script id="88">
          <Name>TicketCreateTaskInToDoCommand</Name>
          <Code>using Alvao.API.Common;
using Alvao.API.Common.Model.CustomApps;
using Alvao.Apps.API;
using Alvao.API.Common.Model.Database;
using MessageType = Alvao.API.Common.Model.CustomApps.MessageType;
using Alvao.API.Common.Exceptions;
using System.Threading.Tasks;
using System.Linq;
using System.Collections.Generic;
using System;
using System.Threading;
using Microsoft.Kiota.Abstractions.Authentication;

public class TicketCreateTaskInToDoCommand : IEntityCommand
{
    public string Id { get; set; }
    public Entity Entity { get; set; }

    public TicketCreateTaskInToDoCommand()
    {
        Id = "TicketCreateTaskInToDo";
        Entity = Entity.Request;
    }

    public EntityCommandShowResult Show(int entityId, int personId)
    {
        int position = 2;
        string icon = "clipboard_task_add_20_regular";
        string name = "Create task";
        bool show = false;

        tHdTicket ticket = Alvao.API.SD.Ticket.GetById(entityId);

        if (ticket != null &amp;&amp; ticket.liHdTicketHdSectionId &gt; 0)
        {
            var teamRoles = PersonRights.TicketRoles.SectionManager | PersonRights.TicketRoles.SectionMainSolver | PersonRights.TicketRoles.SectionSolver;
            show = PersonRights.HaveTicketRole(personId, entityId, ticket.liHdTicketHdSectionId, teamRoles, true);
        }

        if (show)
        {
            show = !string.IsNullOrEmpty(Person.GetById(personId).AzureAdObjectId);
        }

        return new EntityCommandShowResult(show, name, icon, position);
    }

    public CommandResult Run(int entityId, int personId)
    {
        MessageType messageType = MessageType.None;
        string messageText = string.Empty;
        string navigateToUrl = string.Empty;

        try
        {
            Microsoft.Graph.GraphServiceClient graphClient = CreateGraphApiClient(personId, "https://graph.microsoft.com/.default");

            // Get ticket info
            var waUrl = DbProperty.WebAppUrl;
            var ticket = Alvao.API.SD.Ticket.GetById(entityId);
            var ticketFullName = Settings.GetSubject(ticket.sHdTicket, ticket.sHdTicketMessageTag);
            var ticketUrl = "";
            if (!string.IsNullOrEmpty(waUrl))
            {
                ticketUrl = waUrl + "/Ticket/" + entityId;
            }

            var todoTask = new Microsoft.Graph.Models.TodoTask
            {
                Title = ticketFullName,
                LinkedResources = new List&lt;Microsoft.Graph.Models.LinkedResource&gt;
                {
                    new Microsoft.Graph.Models.LinkedResource
                    {
                        WebUrl = ticketUrl,
                        ApplicationName = "Alvao",
                        DisplayName = ticketUrl,
                        ExternalId = entityId.ToString()
                    }
                }
            };

            var listsTask = Task.Run(async () =&gt; await graphClient.Me.Todo.Lists.GetAsync());
            var lists = listsTask.GetAwaiter().GetResult();

            if (lists != null &amp;&amp; lists.Value.Any())
            {
                var postTask = Task.Run(async () =&gt; await graphClient.Me.Todo.Lists[lists.Value.First().Id].Tasks.PostAsync(todoTask));
                postTask.GetAwaiter().GetResult();

                messageType = MessageType.Info;
                messageText = "A new task has been created. Check your MS To Do list.";
            }
            else
            {
                messageType = MessageType.Warning;
                messageText = "The new task couldn't be created.";
            }
        }
        catch
        {
            messageType = MessageType.Error;
            messageText = "The new task could not be created because the application does not have the necessary permissions to your To Do. Please contact your administrator.";
            return new CommandResult(messageType, messageText, navigateToUrl);
        }

        return new CommandResult(messageType, messageText, navigateToUrl);
    }

    private Microsoft.Graph.GraphServiceClient CreateGraphApiClient(int personId, string scope)
    {
        try
        {
            return new Microsoft.Graph.GraphServiceClient(
                new BaseBearerTokenAuthenticationProvider(
                    new TokenProvider(personId, scope)
                )
            );
        }
        catch (UserTokenServiceError)
        {
            return null;
        }
    }
}

public class TokenProvider : IAccessTokenProvider
{
    private readonly int personId;
    private readonly string scope;

    public TokenProvider(int personId, string scope)
    {
        this.personId = personId;
        this.scope = scope;
    }

    public Task&lt;string&gt; GetAuthorizationTokenAsync(Uri uri, Dictionary&lt;string, object&gt; additionalAuthenticationContext = default,
        CancellationToken cancellationToken = default)
    {
        var token = Alvao.API.Internal.UserToken.GetToken(personId, scope);
        if (string.IsNullOrEmpty(token))
            return null;
        return Task.FromResult(token);
    }

    public AllowedHostsValidator AllowedHostsValidator { get; }
}</Code>
          <IsLibCode>false</IsLibCode>
          <Codesign>l3Ztii+53P0Fp/bi5+wefKhU+V2u6ZDxtDOR9z+b4Tmuz/UhMypRM0nPLDT267pV3lSdXLqhZQqUrHXWjzwCDASzq6BT0nO8IOvq8gquznTOxULX6b9HLg4yR4akGOkwpPcETMGsVp2nMHY139LyrO/CIXPhD3mSLtDpOg/s6hqLwgcbexsypQz6SCeUcpoVy59h9OrM1VgZlfHQGPyzdwbUgTT6HZFz+jUKRf2ejxqv5xgiv57lY/LTP386YmUQ6b/q0pB1MRbSjVXfbfPY8u8ohr5lP1yCZZ56eXnAggwaEFT2k3ZmR8vGBJpi7O6EM/40Xhr95fbLiOv9QrBHTA==</Codesign>
        </Script>
        <Script id="89">
          <Name>Settings</Name>
          <Code>public class Settings
{
    private static int subjectMaxLength = 150;
    private static string dots = "...";

    public static string GetSubject (string name, string tag)
    {
        string ticketFullName;
        if (name.Length &gt; 150)
        {
            name = $"{name.Trim().Substring(0, subjectMaxLength - 1)}";
            ticketFullName = $"{name}{dots} ({tag})"; 
        }
        else
        {
            ticketFullName = $"{name} ({tag})"; 
        }

        return ticketFullName;
    }
}</Code>
          <IsLibCode>true</IsLibCode>
          <Codesign>JzGQnVChfkCOIqiM+O+NO0qnLFxX3jr0G59Be8THP4d4b/6O3t81JRaXfReU1aFKAIYSSNkKbvm5+iVqSclDLg/kTfvXnTakig5wrADI78OHvI7Mw3v5o8l4N/O9CbwLGNhNwnVzZvvmyMyfv3PzmZo03H5M2CdS1sKRVTPKVv+uR3Jo8JyMxOAsJy3XoOfYT7sJ2U8QxnGTpi5S5cdlT8n3RB/qkQScJMHpd2B1HKcvZut13h/WI3EVzHM3lgnopA5jJny/WH0ACnWoLrU2j9nVhzcem+OXHPRTZU79tWx3cFzi+mdeTGJjsJ/OTjx4bHG2IxshkJUc1oxbx7T1ew==</Codesign>
        </Script>
      </Scripts>
    </Application>
  </Applications>
</AlvaoApplication>