Aller au contenu

Script de routage des appels

De INDYWiki
#nullable disable
using CallFlow;
using System;
using System.Threading.Tasks;
using TCX.Configuration;
using TCX.PBXAPI;
using System.Collections.Generic;
using System.Linq;
using CallFlow.CFD;

namespace interceptcall
{
    public class InterceptInboundCall : ScriptBase<InterceptInboundCall>
    {
        // Destination par Défaut
        const string DefaultDestinationDN = "600";

        // Structure d'une règle de routage
        class RoutingRule
        {
            public Schedule Schedule { get; set; }
            public string DestinationDN { get; set; }
            public string[] DIDs { get; set; }
            public string[] Callers { get; set; }

            public RoutingRule(Schedule schedule, string destinationDN, string[] dids, string[] callers)
            {
                Schedule = schedule;
                DestinationDN = destinationDN;
                DIDs = dids;
                Callers = callers;
            }
        }


// Règle(s) de routage. La première règle trouvée satisfaite sera la route suivie
       static readonly List<RoutingRule> routingRules = new List<RoutingRule>
        {
            // RULE 1 — Nuit semaine → 990
            new RoutingRule(
                new Schedule(RuleHoursType.SpecificHours)
                {
                    { DayOfWeek.Monday,    new Schedule.PeriodOfDay(TimeSpan.FromHours(17.5), TimeSpan.FromHours(24)) },
                    { DayOfWeek.Monday,    new Schedule.PeriodOfDay(TimeSpan.FromHours(0), TimeSpan.FromHours(7)) },
                    { DayOfWeek.Tuesday,   new Schedule.PeriodOfDay(TimeSpan.FromHours(17.5), TimeSpan.FromHours(24)) },
                    { DayOfWeek.Tuesday,   new Schedule.PeriodOfDay(TimeSpan.FromHours(0), TimeSpan.FromHours(7)) },
                    { DayOfWeek.Wednesday, new Schedule.PeriodOfDay(TimeSpan.FromHours(17.5), TimeSpan.FromHours(24)) },
                    { DayOfWeek.Wednesday, new Schedule.PeriodOfDay(TimeSpan.FromHours(0), TimeSpan.FromHours(7)) },
                    { DayOfWeek.Friday,    new Schedule.PeriodOfDay(TimeSpan.FromHours(17.5), TimeSpan.FromHours(24)) },
                    { DayOfWeek.Friday,    new Schedule.PeriodOfDay(TimeSpan.FromHours(0), TimeSpan.FromHours(7)) }
                },
                "600",
                new[] { "*" },   // Tous les DIDs
                new[] { "*" }    // Tous les callers
            ),

            // RULE 2 — Jeudi 14h-18h → 804 (DID spécifique)
            new RoutingRule(
                new Schedule(RuleHoursType.SpecificHours)
                {
                    { DayOfWeek.Thursday, new Schedule.PeriodOfDay(TimeSpan.FromHours(14), TimeSpan.FromHours(16.25)) }
                },
                "804",
                new[] { "*" }, // DID spécifique
                new[] { "*" }
            ),
            
              // RULE 3 — Jeudi 14h-18h → 805
            new RoutingRule(
                new Schedule(RuleHoursType.SpecificHours)
                {
					{ DayOfWeek.Thursday, new Schedule.PeriodOfDay(new TimeSpan(17,15,0), new TimeSpan(17,30,0)) },
                },
                "805",
                new[] { "*" },
                new[] { "*" }
            ),

            // RULE 4 — Week-end complet → 992
            new RoutingRule(
                new Schedule(RuleHoursType.SpecificHours)
                {
                    { DayOfWeek.Saturday, new Schedule.PeriodOfDay(TimeSpan.FromHours(0), TimeSpan.FromHours(24)) },
                    { DayOfWeek.Sunday,   new Schedule.PeriodOfDay(TimeSpan.FromHours(0), TimeSpan.FromHours(24)) }
                },
                "992",
                new[] { "*" },
                new[] { "*" }
            )
        };

        // Appel de la fonction principale

        public override async void Start()
        {
            try
            {
                await Task.Run(async () =>
                {
                    bool intercepted = false;
                    var ps = MyCall.PS as PhoneSystem;

                    if (!(MyCall.Caller.DN is ExternalLine externalLine))
                    {
                        MyCall.Return(false);
                        return;
                    }

                    var DIDNumber = MyCall.Caller["inbound_did"] ?? "";
                    var CallerID = MyCall.Caller.CallerID ?? "";
                    var currentTime = externalLine.Now(out var utc, out var timezone, out var groupmode);

                    MyCall.Info($"Incoming call | Caller: {CallerID} | DID: {DIDNumber} | Time: {currentTime}");

                    foreach (var rule in routingRules)
                    {
                        if (!rule.Schedule.IsActiveTime(currentTime))
                            continue;

                        bool didMatch = rule.DIDs.Contains("*") || rule.DIDs.Contains(DIDNumber);
                        bool callerMatch = rule.Callers.Contains("*") || rule.Callers.Contains(CallerID);

                        if (!didMatch || !callerMatch)
                            continue;

                        var destinationDN = ps.GetDNByNumber(rule.DestinationDN);

                        if (destinationDN == null)
                        {
                            MyCall.Error($"Destination {rule.DestinationDN} not found.");
                            continue;
                        }

                        try
                        {
                            var result = await MyCall.RouteToAsync(new DestinationStruct(destinationDN));
                            MyCall.Info($"Routed to {rule.DestinationDN} | Result: {result}");
                            intercepted = true;
                            break; // Stop at first matching rule
                        }
                        catch (Exception ex)
                        {
                            MyCall.Error($"Routing failed to {rule.DestinationDN}: {ex}");
                        }
                    }

                
                    // Utilisation de la route par défaut
                    
                    if (!intercepted)
                    {
                        var fallbackDN = ps.GetDNByNumber(DefaultDestinationDN);
                        if (fallbackDN != null)
                        {
                            try
                            {
                                var result = await MyCall.RouteToAsync(new DestinationStruct(fallbackDN));
                                MyCall.Info($"Fallback routing to {DefaultDestinationDN} | Result: {result}");
                                intercepted = true;
                            }
                            catch (Exception ex)
                            {
                                MyCall.Error($"Fallback routing failed: {ex}");
                            }
                        }
                        else
                        {
                            MyCall.Error($"Fallback DN {DefaultDestinationDN} not found.");
                        }
                    }

                    MyCall.Return(intercepted);
                });
            }
            catch (Exception ex)
            {
                MyCall.Error($"Script execution failed: {ex}");
                MyCall.Return(false);
            }
        }
    }
}